2017-02-15 3 views
2

J'ai toujours été dérouté par les types de variables dans R. Maintenant, j'ai rencontré un problème après la transposition d'une trame de données.R changements de types de variables après la transposition d'une trame de données

Par exemple, j'utilise table() pour obtenir un compte de chaque facteur dans un certain vecteur:

data(iris) 

count <- as.data.frame(table(iris$Species)) 
typeof(count$Var1) 
# [1] "integer" 

typeof(count$Freq) 
# [1] "integer" 

Ma 1ère question serait, pourquoi est-count$Var1 « entier »? Les chaînes peuvent-elles être "entières" aussi? Mais cela n'a pas d'importance car je peux changer le type par count$Var1 <- as.character(count$Var1), puis typeof(count$Var1) devient "personnage".

Maintenant, je transpose cette trame de données par transposed_count <- as.data.frame(t(count)). Mais je confonds parce que:

typeof(transposed_count[1,]) 
[1] "list" 

typeof(transposed_count[2,]) 
[1] "list" 

transposed_count[2,] 
    V1 V2 V3 
Freq 50 50 50 

En conséquence, je dois transposed_count[2,] d'être un vecteur numérique comme:

transposed_count[2,] 
[1] 50 50 50 

Comment puis-je faire cela? Et pourquoi sont-ils devenus "liste" après t()? Désolé si c'est une question stupide. Merci!

Répondre

3

Ma première question serait, pourquoi est count$Var1 "entier"?

Parce que les facteurs sont ont le même type de stockage entier

> is.factor(count$Var1) 
[1] TRUE 

et les "cordes" dans l'iris data.frame, comme cela est typique dans R, sont stockés sous forme de facteurs.

Et pourquoi sont-ils devenus "liste" après t()? Lorsque vous transposez, vous obtenez une matrice et les matrices doivent avoir la même classe de stockage pour chaque entrée. Ce que vous obtiendrez en premier est une matrice de caractères, car les valeurs entières seront forcées. Ensuite, lorsque vous changez par la suite en data.frame, ces caractères seront forcés par défaut à (nouveaux) facteurs.

> t(count) 
    [,1]  [,2]   [,3]  
Var1 "setosa" "versicolor" "virginica" 
Freq "50"  "50"   "50" 

> transposed_count <- as.data.frame(t(count)) 

> transposed_count[2,1] 
Freq 
    50 
Levels: 50 setosa 
> as.numeric(transposed_count[2,1]) 
[1] 1 

Alors ce qui était un compte de 50 est maintenant un facteur avec une valeur numérique de 1! Pas ce que tu veux.

En ce qui concerne pourquoi typeof(transposed_count[1,]) est une liste? Comme une tranche horizontale d'un data.frame, il s'agit en fait d'un data.frame.

> is.data.frame(transposed_count[2,]) 
[1] TRUE 

Et data.frames sont juste des listes avec des informations de classe.Mais comment puis-je obtenir une trame de données "transposée" alors?

Il semble que vous pouvez

> library(reshape2) 
> dcast(melt(count), variable~Var1) 
Using Var1 as id variables 
    variable setosa versicolor virginica 
1  Freq  50   50  50 

après avoir lu tous les échantillons, je vais rbind toutes les trames de données

Vous devrez assurer les colonnes alignez de façon appropriée. Selon l'analyse à venir, il peut être plus naturel de rbind comme c'est le cas avec une autre colonne indiquant la source.

> count2 <- count 
> count$source = "file1" 
> count2$source = "file2" 
> (mcount <- rbind(count,count2)) 
     Var1 Freq source 
1  setosa 50 file1 
2 versicolor 50 file1 
3 virginica 50 file1 
4  setosa 50 file2 
5 versicolor 50 file2 
6 virginica 50 file2 

Maintenant, vous n'avez pas à vous soucier de l'alignement si vous ne souhaitez remodeler plus tard

> dcast(melt(mcount), ...~Var1) 
Using Var1, source as id variables 
    source variable setosa versicolor virginica 
1 file1  Freq  50   50  50 
2 file2  Freq  50   50  50 
+0

Merci pour l'explication! Cela est devenu plus clair pour moi. Mais comment puis-je obtenir une trame de données "transposée" alors? – Yan

+0

Je lis dans un tas de fichiers, chaque fichier que chaque échantillon. Enfin, j'ai besoin d'un cadre de données où les lignes sont des échantillons, les colonnes sont le nombre de chaque élément dans chaque fichier/échantillon. Donc, après avoir lu tous les échantillons, je vais relier toutes les données. C'est pourquoi j'ai besoin d'être transposé. Je vais mettre le "Var1" comme colnames pour le cadre de données final. – Yan

+0

Comme l'a déduit @Roman Luštrik, vous recherchez probablement quelque chose comme 'dcast (melt (count), ... ~ Var1)' dans la bibliothèque 'reshape2'. Cependant, en fonction de votre analyse à venir, la forme la plus naturelle peut être de «lier» les données dans leur format original, en ajoutant une autre colonne avec un indicateur de fichier/échantillon. Cela vous donnerait un format "empilé". –

3

typeof vous dira comment R stocke les données en interne. Pour les facteurs, ceci est un entier. Et Var1 est un facteur, voir?

> class(count$Var1) 
[1] "factor" 

transposed_counts n'a aucun sens dans ce cas. En transposant vous détruisez la logique data.frame. Transposer a généralement du sens pour les matrices. Si vous voulez "refaire" un data.frame, vous pouvez utiliser quelque chose comme reshape ou l'un de ses proches.

+0

Merci pour la réponse! – Yan

0

Si vous faites les noms des espèces en Var1 dans les noms de ligne avant de transposer à éviter les problèmes avec la transposition convertir tout à un même type de données.

data(iris) 
count <- as.data.frame(table(iris$Species)) 
row.names(count) <- count$Var1 
count$Var1 <- NULL 
transposed_count <- as.data.frame(t(count)) 
as.numeric(transposed_count[1,]) 
# [1] 50 50 50