Obtenir le code ASCII d'un caractère

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Florian Sorin
Messages : 30
Enregistré le : 13 Mai 2008, 09:40

Obtenir le code ASCII d'un caractère

Messagepar Florian Sorin » 01 Juil 2008, 07:40

Bonjour,

Je dispose d'une grille "virtuelle", correspondant à un quadrillage sur une carte. Chacune des mailles (cases) de cette grille est référencée par une abscisse (caractères) et une ordonnée (nombre). J'ai ainsi 793848 cases référencées de A1 à iA744.

J'ai une liste de cases extraites de cette grille parce qu'elles présentent un intérêt particulier.
Je voudrais pour toutes ces cases extraites, déterminer lesquelles sont voisines les unes des autres dans la grille (adjacentes ou ayant un coin en commun), c'est à dire obtenir une matrice de voisinage de ce style:

Code : Tout sélectionner

     A1  A2  B3 C2
A1  0    1    0   0
A2  1    0    1   0
B3  0    1    0   1
C2  0    0    1   0



(0 indique que les cases sont distantes (ou confondues), 1 indique qu'elles sont voisines).


Pour déterminer si deux cases sont voisines, je compare la partie "caractères" et la partie "nombres" séparément. Pour les nombres pas de problème,mais pour les caractères, je ne vois pas vraiment comment déterminer si deux caractères se suivent dans l'alphabet, et de plus, certains caractères utilisés ne sont pas des lettres (" ] _ \ ^ ").
En revanche, les codes ASCII de tous ces caractères se suivent. Je voudrais donc récupérer ces codes ASCII pour effectuer des comparaisons du genre:

Code : Tout sélectionner

if(code_ascii(substr(case1,2,2)) == code_ascii(substr(case2,2,2))+1) {...}


Y'a-t-il un moyen de faire cela? Je n'ai pas trouvé de fonction correspondante.

Merci d'avance.

Julien Barnier
Messages : 45
Enregistré le : 24 Juin 2008, 13:19
Contact :

Messagepar Julien Barnier » 01 Juil 2008, 08:54

Si on cherche "ascii code" dans http://www.rseek.org, on tombe notamment sur le message suivant :

http://tolstoy.newcastle.edu.au/R/help/02a/0961.html

Qui suggère l'utilisation de :

Code : Tout sélectionner

ascii <- sapply(1:127,function(i) parse(text=paste("\"\\",structure(i,class="octmode"),"\"",sep=""))[[1]])


Pour obtenir le caractère ayant le code 65 :

Code : Tout sélectionner

ascii[65]


Pour obtenir le code ASCII du caractère 'A' :

Code : Tout sélectionner

 which(ascii == 'A')

Florian Sorin
Messages : 30
Enregistré le : 13 Mai 2008, 09:40

Messagepar Florian Sorin » 01 Juil 2008, 09:11

Merci beaucoup, ça fonctionne.

Je ne connaissais pas le site rseek.org, il semble très utile.

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Juste une idée

Messagepar Serge Rapenne » 01 Juil 2008, 10:12

Si ta grille virtuelle est une liste et que les références de ta grille sont classées de gauche à droite et de haut en bas par exemple pour une grille 5x5 :

Code : Tout sélectionner

indice_liste            référenceGrille
1                               A1
2                               A2
3                               A3
4                               A4
5                               A5
...                              ...
24                              E4
25                              E5


Si ta grille à NBCOL colonnes, si tu cherches les voisins d'une maille dont l'indice est X, les 8 voisins vont avoir pour indice X-NBCOL-1,X-NBCOL,X-NBCOL+1,X-1,X+1,X+NBCOL-1,X+NBCOL et X+NBCOL+1 ce qui sera vraisemblablement plus rapide que de tester les références de la grille.

Amicalement

Florian Sorin
Messages : 30
Enregistré le : 13 Mai 2008, 09:40

Messagepar Florian Sorin » 01 Juil 2008, 11:53

Au départ je voulais obtenir une matrice de voisinage de l'ensemble de la grille, en utilisant votre méthode qui est bien plus simple effectivement (même s'il faut gérer les débuts et fins de lignes et de colonnes). Ensuite j'aurais extrait de cette matrice les lignes et colonnes correspondant aux cases qui m'intéressent.

Mais le problème est que R ne supporte pas une matrice de 793848 lignes par 793848 colonnes.

Du coup je suis obligé de créer la matrice de voisinage uniquement pour les cases qui m'intéressent, à partir d'une liste comme celle ci:

Code : Tout sélectionner

indice          case
1                   A1
2                   A2
3                   B2
4                   C3


Je ne peux donc plus utiliser les indices directement.
Je devrais parcourir la liste complète des cases de la grille et tester pour chacune d'entre elles si elle fait partie de la liste des cases qui m'intéressent. Si c'est le cas je vais chercher ses voisins, en testant pour chacun s'ils font aussi partie des cases qui m'intéressent.

Du coup j'ai préféré me lancer dans la comparaison des références pour éviter des temps d'exécution interminables dûs aux boucles de parcours des listes et qui a en plus l'avantage (ça je m'en suis rendu compte plus tard) de ne pas avoir à gérer les débuts et fins de lignes et de colonnes comme des cas particuliers.

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Autre piste

Messagepar Serge Rapenne » 01 Juil 2008, 13:29

Tu y as certainement pensé mais je me demande s'il n'est pas possible de calculer un pseudo_indice à partir des références de la grille et d'utiliser la technique des indices. Avec un truc du genre (si les lettres sont les lignes)

Code : Tout sélectionner

pseudo_indice<-(ascii(substr(case,1,1))-65)*NBCOL+substr(case,2,2)

dans ce cas pseudo_indice(A2)=0*NBCOL+2=2 ou pseudo_indice(B3)=1*NBCOL+3
à adapter au nombre de caractère de ton champs "case"

Je pousse un peu car ton problème est d'un genre que je risque d'avoir un jour ou l'autre ;-)

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Messagepar François Bonnot » 01 Juil 2008, 14:05

Bonjour,
1) Pour les caractères ASCII

Code : Tout sélectionner

> as.integer(charToRaw("A"))
[1] 65
> rawToChar(as.raw(65))
[1] "A"


2) Il serait plus simple d'utiliser directement des coordonnées numériques plutôt que des lettres et des nombres. Mais si on persiste dans cette voie on peut passer au numérique comme ceci par exemple :

Code : Tout sélectionner

> grille <- c("A1","A2","B3","C2")
> lettre <- sapply(grille,substr,1,1)
> x <- sapply(lettre,function(x) as.integer(charToRaw(x)))
> y <- as.integer(sapply(strsplit(grille,"[[:alpha:]]"),"[",2))
> (df <- cbind(x,y))
    x y
A1 65 1
A2 65 2
B3 66 3
C2 67 2


3) Il y a des packages qui calculent très bien les matrices de proximité, par exemple spdep :

Code : Tout sélectionner

> library(spdep)
> nb<-dnearneigh(df,d1=0.0,d2=1.5)
> unclass(nb)
[[1]]
[1] 2

[[2]]
[1] 1 3

[[3]]
[1] 2 4

[[4]]
[1] 3

(...)


ce qui se lit :
le site 1 a pour voisin le site 2
le site 2 a pour voisins les sites 1 et 3
etc

Si on préfère une matrice (pas forcément la meilleure solution à cause de la taille):

Code : Tout sélectionner

> (mat <- nb2mat(nb,style='B',zero.policy=TRUE))
  [,1] [,2] [,3] [,4]
1    0    1    0    0
2    1    0    1    0
3    0    1    0    1
4    0    0    1    0

(...)


FB

Florian Sorin
Messages : 30
Enregistré le : 13 Mai 2008, 09:40

Re: Autre piste

Messagepar Florian Sorin » 01 Juil 2008, 15:04

Serge Rapenne a écrit :Tu y as certainement pensé mais je me demande s'il n'est pas possible de calculer un pseudo_indice à partir des références de la grille et d'utiliser la technique des indices. Avec un truc du genre (si les lettres sont les lignes)

Code : Tout sélectionner

pseudo_indice<-(ascii(substr(case,1,1))-65)*NBCOL+substr(case,2,2)

dans ce cas pseudo_indice(A2)=0*NBCOL+2=2 ou pseudo_indice(B3)=1*NBCOL+3
à adapter au nombre de caractère de ton champs "case"

Je pousse un peu car ton problème est d'un genre que je risque d'avoir un jour ou l'autre ;-)


Et non je n'y avais pas pensé, mais ça me parait être la solution la plus
simple.

-------
EDIT: Après réflexion, ça ne fonctionnerait pas dans mon cas parce que les références de certaines cases contiennent plusieurs caractères et plusieurs chiffres.
-------

Malgré tout je m'en suis sorti en comparant les références des cases.



Pour les coordonnées alphanumériques, ce n'est pas vraiment un choix: la grille a été générée automatiquement par un logiciel SIG. Mais je suis d'accord avec vous, un x et y numériques sont infiniment plus simples à manipuler et c'est vrai que j'aurais pu les traduire (là non plus je n'y ai pas pensé).


En ce qui concerne les fonctions qui calculent les matrices de proximité, quel type de données faut-il passer en paramètre? une liste de voisins pour chaque site? une matrice de distance?

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Messagepar François Bonnot » 01 Juil 2008, 15:57

En ce qui concerne les fonctions qui calculent les matrices de proximité, quel type de données faut-il passer en paramètre? une liste de voisins pour chaque site? une matrice de distance?

Dans l'exemple précédent, nb est un objet de classe "nb" (= liste de voisins) créé puis utilisé par des fonctions du package spdep :

Code : Tout sélectionner

> nb
Neighbour list object:
Number of regions: 4
Number of nonzero links: 6
Percentage nonzero weights: 37.5
Average number of links: 1.5

C'est un objet de cette classe qui doit être passé à nb2mat pour obtenir une matrice.
Mais on peut manipuler directement et plus efficacement l'objet nb (comme une liste) plutôt que la matrice résultante, celle-ci comportant surtour des zéros.
Exemple :

Code : Tout sélectionner

> nb[[2]]
[1] 1 3


FB


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité