web-dev-qa-db-fra.com

Devrais-je utiliser un data.frame ou une matrice?

Quand faut-il utiliser un data.frame et quand est-il préférable d'utiliser un matrix?

Les deux conservent les données dans un format rectangulaire, de sorte que parfois ce n'est pas clair.

Existe-t-il des règles générales permettant de savoir quand utiliser quel type de données?

142
microbe

Votre question contient déjà une partie de votre réponse: Vous utilisez des blocs de données si vous pouvez vous attendre à ce que les colonnes (variables) soient de types différents (numérique/caractère/logique, etc.). Les matrices sont pour des données du même type. 

Par conséquent, le choix matrix/data.frame ne pose problème que si vous avez des données du même type.

La réponse dépend de ce que vous allez faire avec les données de data.frame/matrix. S'il doit être passé à d'autres fonctions, le type attendu des arguments de ces fonctions détermine le choix.

Également:

Les matrices sont plus efficaces en mémoire:

m = matrix(1:4, 2, 2)
d = as.data.frame(m)
object.size(m)
# 216 bytes
object.size(d)
# 792 bytes

Les matrices sont une nécessité si vous envisagez de faire des opérations de type algèbre linéaire.

Les trames de données sont plus pratiques si vous vous référez souvent à ses colonnes par leur nom (via l'opérateur compact $).

Les trames de données sont également meilleures à mon humble avis pour le rapport (impression) des informations tabulaires, car vous pouvez appliquer le formatage à chaque colonne séparément.

170
Michał

@ Michal ne mentionne pas le fait qu’une matrice est non seulement plus petite que le bloc de données équivalent, l’utilisation de matrices peut rendre votre code beaucoup plus efficace que l’utilisation de blocs de données, souvent considérablement. C'est l'une des raisons pour lesquelles, en interne, de nombreuses fonctions R vont contraindre à des matrices de données contenues dans des trames de données.

Les trames de données sont souvent beaucoup plus pratiques; on ne dispose pas toujours de fragments atomiques de données.

Notez que vous pouvez avoir une matrice de caractères. il ne suffit pas d'avoir des données numériques pour construire une matrice en R.

Lors de la conversion d'un bloc de données en matrice, notez qu'il existe une fonction data.matrix(), qui gère les facteurs de manière appropriée en les convertissant en valeurs numériques basées sur les niveaux internes. La contrainte via as.matrix() créera une matrice de caractères si l’une des étiquettes de facteur est non numérique. Comparer:

> head(as.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
     a   B  
[1,] "a" "A"
[2,] "b" "B"
[3,] "c" "C"
[4,] "d" "D"
[5,] "e" "E"
[6,] "f" "F"
> head(data.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
     a B
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 4 4
[5,] 5 5
[6,] 6 6

J'utilise presque toujours un bloc de données pour mes tâches d'analyse des données car j'ai souvent plus que des variables numériques. Lorsque je code pour des paquetages, je force presque toujours à matrice, puis je reformule les résultats sous forme de trame de données. En effet, les trames de données sont pratiques.

72
Gavin Simpson

@ Michal: Les matrices ne sont pas vraiment plus efficaces en mémoire:

m <- matrix(1:400000, 200000, 2)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 1600776 bytes

... sauf si vous avez un grand nombre de colonnes:

m <- matrix(1:400000, 2, 200000)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 22400568 bytes
46
petrelharp

La matrice est en réalité un vecteur avec des méthodes supplémentaires. tandis que data.frame est une liste . La différence est réduite à vector vs list pour l'efficacité du calcul, coller avec la matrice. Utiliser data.frame si vous devez.

9
user8341

Les matrices et les cadres de données sont des tableaux 2D rectangulaires et peuvent être hétérogène par rangées et colonnes . Ils partagent certaines méthodes et propriétés, mais pas tous.

Exemples:

M <- list(3.14,TRUE,5L,c(2,3,5),"dog",1i)  # a list
dim(M) <- c(2,3)                           # set dimensions
print(M)                                   # print result

#      [,1]  [,2]      [,3]
# [1,] 3.14  5         "dog"
# [2,] TRUE  Numeric,3 0+1i

DF <- data.frame(M)                   # a data frame
print(DF)                             # print result

#      X1      X2   X3
#  1 3.14       5  dog
#  2 TRUE 2, 3, 5 0+1i

M <- matrix(c(1,1,1,1,2,3,1,3,6),3)   # a numeric matrix
DF <- data.frame(M)                   # a all numeric data frame

solve(M)                              # obtains inverse matrix
solve(DF)                             # obtains inverse matrix
det(M)                                # obtains determinant
det(DF)                               # error
0
Trisquel

Je ne peux pas insister davantage sur la différence d'efficacité entre les deux! S'il est vrai que les FD sont plus pratiques dans certains cas d'analyse de données en particulier, ils autorisent également les données hétérogènes, et certaines bibliothèques ne les acceptent que, mais tout cela est vraiment secondaire sauf si vous écrivez un code ponctuel pour une tâche spécifique. 

Laisse moi te donner un exemple. Une fonction calculait le chemin 2D de la méthode MCMC. En gros, cela signifie que nous prenons un point initial (x, y) et itérons un certain algorithme pour trouver un nouveau point (x, y) à chaque étape, en construisant ainsi le chemin complet. L'algorithme implique le calcul d'une fonction assez complexe et la génération d'une variable aléatoire à chaque itération. Ainsi, lorsqu'il s'exécutait pendant 12 secondes, je pensais que tout allait bien compte tenu du nombre de choses qu'il effectuait à chaque étape. Cela dit, la fonction a collecté tous les points du chemin construit ainsi que la valeur d'une fonction objectif dans un fichier data.frame à 3 colonnes. Donc, 3 colonnes n’est pas si grande, et le nombre d’étapes était également plus que raisonnable. 10 000 (dans ce genre de problèmes, des trajets d’une longueur de 1 000 000 sont typiques, donc 10 000 n’est rien). J'ai donc pensé qu'un DF 10 000 x 3 n'était définitivement pas un problème. La raison pour laquelle un DF a été utilisé est simple. Après avoir appelé la fonction, ggplot () a été appelé pour dessiner le chemin (x, y) résultant. Et ggplot () n'accepte pas de matrice. 

Puis, par curiosité, j'ai décidé de changer de fonction pour collecter le chemin dans une matrice. Heureusement, la syntaxe des DF et des matrices est similaire, je n’ai fait que modifier la ligne spécifiant df en tant que data.frame pour l’initialiser en tant que matrice. Ici, je dois aussi mentionner que dans le code initial, le DF a été initialisé pour avoir la taille finale. Ainsi, plus tard dans le code de la fonction, seules les nouvelles valeurs ont été enregistrées dans des espaces déjà alloués, et il n’ya pas de surcharge à ajouter. nouvelles lignes dans le DF. Cela rend la comparaison encore plus juste, et cela simplifie également mon travail, car je n'ai pas besoin de réécrire quoi que ce soit dans la fonction. Une seule ligne suffit pour passer de l'allocation initiale d'un data.frame de la taille requise à une matrice de la même taille. Pour adapter la nouvelle version de la fonction à ggplot (), j'ai converti la matrice maintenant renvoyée en un fichier data.frame à utiliser dans ggplot (). 

Après avoir relu le code, je ne pouvais pas en croire le résultat. Le code a fonctionné en une fraction de seconde! Au lieu d'environ 12 secondes. Et encore une fois, pendant les 10 000 itérations, la fonction a uniquement lu et écrit des valeurs dans des espaces déjà alloués dans un DF (et maintenant dans une matrice). Et cette différence est également valable pour la taille raisonnable (ou plutôt petite) 10000x3. 

Donc, si votre seule raison d'utiliser un DF est de le rendre compatible avec une fonction de bibliothèque telle que ggplot (), vous pouvez toujours le convertir en un DF au dernier moment - travailler avec des matrices dans la mesure où vous vous sentez à l'aise. Si, par contre, il existe une raison plus substantielle d’utiliser un FD, par exemple, vous utilisez un logiciel d’analyse de données qui nécessiterait sinon une transformation constante des matrices en DF et inversement, ou vous ne faites pas de calculs intensifs vous-même et n’utilisez que des tests standard. packages (beaucoup d’entre eux transforment en interne un DF en matrice, font leur travail, puis retransforment le résultat - pour qu’ils fassent tout le travail d’efficacité pour vous), ou fassent un travail ponctuel pour vous; ne vous inquiétez pas et ne vous sentez pas plus à l'aise avec les FD, vous ne devriez donc pas vous soucier de l'efficacité 

Ou une autre règle plus pratique: si vous avez une question comme dans le PO, utilisez des matrices. Vous n’utiliserez donc les FD que lorsque vous n’avez pas cette question (car vous savez déjà que vous devez les utiliser, ou pas vraiment attention car le code est ponctuel, etc.). 

Mais en général, gardez toujours cette priorité à l’esprit. 

0
Vadim