Transformer des listes en ligne en une table

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

Remy Poncet
Messages : 15
Enregistré le : 05 Juin 2015, 12:31

Transformer des listes en ligne en une table

Messagepar Remy Poncet » 20 Juil 2015, 12:49

Salut,

Je suis face à une manip quoi doit être simple, mais je ne parviens pas à trouver le moyen de le faire:

J'ai une table qui présente dans une seule colonne des listes d'espèces séparées par des espaces " ". J'aimerais transformer ce jeu de données en une table avec des colonnes, une espèce par colonne. Pour corser un peu l'affaire, toutes les listes ne sont pas de la même longueur, et je ne connais pas la longueur maximale de la plus grande liste...

Donc, j'aimerais passer de :

Code : Tout sélectionner

1: SpeciesA SpeciesB SpeciesC SpeciesD SpeciesE
2: SpeciesA SpeciesC SpeciesE SpeciesD SpeciesF SpeciesG SpeciesH
3: SpeciesB SpeciesC SpeciesF
4: SpeciesB SpeciesC SpeciesD SpeciesF SpeciesH
[...]


Vers:

Code : Tout sélectionner

1: SpeciesA | SpeciesB | SpeciesC | SpeciesD | SpeciesE |   NA     |   NA     |
2: SpeciesA | SpeciesC | SpeciesE | SpeciesD | SpeciesF | SpeciesG | SpeciesH |
3: SpeciesB | SpeciesC | SpeciesF |   NA     |   NA     |   NA     |   NA     |
4: SpeciesB | SpeciesC | SpeciesD | SpeciesF | SpeciesH |   NA     |   NA     |
[...]

Une idée?

Merci pour le coup de main!

R.

Eric Casellas
Messages : 767
Enregistré le : 06 Jan 2009, 14:59

Re: Transformer des listes en ligne en une table

Messagepar Eric Casellas » 20 Juil 2015, 13:36

Bonjour,

La fonction strsplit te permet de découper des chaînes de caractères selon un pattern.

exemple :

Code : Tout sélectionner

X <- data.frame(Col1=c(
  "SpeciesA SpeciesB SpeciesC SpeciesD SpeciesE",
  "SpeciesA SpeciesC SpeciesE SpeciesD SpeciesF SpeciesG SpeciesH",
  "SpeciesB SpeciesC SpeciesF",
  "SpeciesB SpeciesC SpeciesD SpeciesF SpeciesH"),
  stringsAsFactors=FALSE)

# on decoupe chaque ligne selon le séparateur espace
tmpX <- sapply(X, strsplit, split=" ")
#on prepare le data.frame final au bonnes dimensions (nbr lignes et colonnes)
newX <- data.frame(matrix(nrow=nrow(X), ncol=max(sapply(1:nrow(X), function(i){length(tmpX[i,]$Col1)}))))
# on rempli newX avec les valeurs de tmpX
for (i in 1:nrow(X)) {
  newX[i,1:length(tmpX[i,]$Col1)] <- tmpX[i,]$Col1
}
Eric

Navarre Julien
Messages : 367
Enregistré le : 20 Avr 2012, 08:27

Re: Transformer des listes en ligne en une table

Messagepar Navarre Julien » 20 Juil 2015, 13:44

Bonjour, d'autres solutions :

Code : Tout sélectionner

# Dès l'importation avec fill = TRUE
datas <- read.table(text = "SpeciesA SpeciesB SpeciesC SpeciesD SpeciesE
SpeciesA SpeciesC SpeciesE SpeciesD SpeciesF SpeciesG SpeciesH
SpeciesB SpeciesC SpeciesF
SpeciesB SpeciesC SpeciesD SpeciesF SpeciesH", sep = " ", fill = TRUE)

# Après importation en utilisant des packages de manipulation de données
datas <- read.table(text = "SpeciesA SpeciesB SpeciesC SpeciesD SpeciesE
SpeciesA SpeciesC SpeciesE SpeciesD SpeciesF SpeciesG SpeciesH
SpeciesB SpeciesC SpeciesF
SpeciesB SpeciesC SpeciesD SpeciesF SpeciesH", sep = "\n", stringsAsFactors = FALSE)

# On a besoin de récupérer le nombre de colonnes qu'il y aura au total pour pouvoir utiliser les fonctions qui vont suivre
datas <- setNames(datas, "col")
con <- textConnection(datas$col)
xlines <- readLines(con)
nCol <- max(vapply(xlines, function(x) length(gregexpr(" ", x)[[1]]), integer(1), USE.NAMES = FALSE)) + 1

library(tidyr)
separate(datas, col, sprintf("col%d", seq_len(nCol)), " ", extra = "drop")

# Comme j'ai vu que vous utilisiez data.table, il faut la version de dev. Ce n'est pas celle dispo sur le CRAN
library(data.table) # => 1.9.5
datas <- as.data.table(datas)
datas[, sprintf("col%d", seq_len(nCol)) := tstrsplit(col, " ", fixed = TRUE)]

# Une autre façon de faire avec strsplit et rbind.fill du package plyr
x <- lapply(datas, strsplit, split = " ")[[1]]
datas <- plyr::rbind.fill(lapply(x, function(y) {
  as.data.frame(t(y), stringsAsFactors = FALSE)}))

Gabriel Terraz
Messages : 593
Enregistré le : 26 Sep 2011, 15:11

Re: Transformer des listes en ligne en une table

Messagepar Gabriel Terraz » 20 Juil 2015, 16:02

Salut,
Il y a la fonction count.fields() qui peut être pratique (elle compte le nombre de champs de chaque ligne du fichier), puis on en prend le maximum qu'on passe en argument soit à col.names, soit colClasses :

Code : Tout sélectionner

nc <- max(count.fields("text"))
tab <- read.table(file , h = F , colClasses = rep("character" , nc) , fill = T , na.string = "" )
tab <- read.table(file , h = F , col.names = paste0("V" , seq_len(nc)) , fill = T , na.string = "" )

Remy Poncet
Messages : 15
Enregistré le : 05 Juin 2015, 12:31

Re: Transformer des listes en ligne en une table

Messagepar Remy Poncet » 21 Juil 2015, 06:35

Salut à tous!

Merci beaucoup d'avoir été aussi vite pour me proposer vos 3 solutions!
Les deux premières fonctionnent sans problème avec les données "test", mais ça ne tournait pas avec mes données que j'avais importées avec readLines":

Code : Tout sélectionner

datas<-readLines("output_from_software",n=-1,ok=T,warn=T,encoding="unknow",skipNul=F)

J'avais des messages d'erreur liés au "format" de données et je ne suis pas parvenu à trouver comment solutionner ça. Bien qu'il doive s'agir d'une simple transformation (mais ça ne m'a pas paru aussi évident après une multitude d'essais).
La solution proposée par Gabriel a été la plus simple. Elle nécessite juste d'écrire dans un fichier texte "datas" au préalable:

Code : Tout sélectionner

write(datas,"datas.txt")
nc <- max(count.fields("datas.txt"))
tab <- read.table("datas.txt" , h = F , col.names = paste0("V" , seq_len(nc)) , fill = T , na.string = "" )

Et voilà!

Merci beaucoup pour votre aide! Ça me permet de continuer!

R.


Retourner vers « Questions en cours »

Qui est en ligne

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

cron