8 votes

Coller le nom de la colonne à chaque valeur d'un cadre de données dans R

J'espère que ce n'est pas une répétition. J'ai fait des recherches mais je n'ai pas trouvé ce que je cherchais.

J'ai un cadre de données (df) dans R.

  1 2 3 4 5 
1 1 0.5 0.5 0 1
2 0.5 0.5 0.5 0 1
3 1 1 0 0 1
4 1 1 0 0 1 
5 1 1 0 0 1

(avec les 1-5 indiquant les noms des lignes et des colonnes)

Je voudrais coller le nom de la colonne dans chaque cellule, en le séparant par un " :", de façon à ce que cela ressemble à ceci :

  1 2 3 4 5 
1 1:1 2:0.5 3:0.5 4:0 5:1 
2 1:0.5 2:0.5 3:0.5 4:0 5:1 
3 1:1 2:1 3:0 4:0 5:1 
4 1:1 2:1 3:0 4:0 5:1 
5 1:1 2:1 3:0 4:0 5:1 

Cependant, mes données réelles sont un peu plus importantes.

J'ai actuellement

apply(df, 2, function(x) paste(colnames(df)[x], x, sep=":"))

Bien sûr, cela ne fonctionne pas car colnames(df)[x] n'a aucun sens. Y a-t-il quelque chose que je puisse mettre dans le premier terme "coller" pour que cela soit trié ? Ou une autre fonction qui ferait un meilleur travail ?

Merci.

6voto

alistaire Points 5898

Pour expliquer mon commentaire, Map est une version multivariée de lapply donc

df <- data.frame(`1` = c(1, 0.5, 1, 1, 1), 
                 `2` = c(0.5, 0.5, 1, 1, 1), 
                 `3` = c(0.5, 0.5, 0, 0, 0), 
                 `4` = c(0L, 0L, 0L, 0L, 0L), 
                 `5` = c(1L, 1L, 1L, 1L, 1L), 
                 check.names = FALSE)

df[] <- Map(paste, names(df), df, sep = ':')

df
##       1     2     3   4   5
## 1   1:1 2:0.5 3:0.5 4:0 5:1
## 2 1:0.5 2:0.5 3:0.5 4:0 5:1
## 3   1:1   2:1   3:0 4:0 5:1
## 4   1:1   2:1   3:0 4:0 5:1
## 5   1:1   2:1   3:0 4:0 5:1

Ici Map prend le premier élément de names(df) c'est-à-dire 1 y paste au premier élément de df c'est-à-dire la première colonne. L'affectation à df[] conserve la classe data.frame de la liste, et donc la structure originale.

Si vos données sont une matrice, vous pouvez faire la même chose avec sweep :

mat <- matrix(c(1, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1), 
              5, 5, 
              dimnames = list(c("1", "2", "3", "4", "5"), 
                              c("1", "2", "3", "4", "5")))

mat[] <- sweep(mat, 2, colnames(df), function(x, y) paste(y, x, sep = ':'))

mat
##   1       2       3       4     5    
## 1 "1:1"   "2:0.5" "3:0.5" "4:0" "5:1"
## 2 "1:0.5" "2:0.5" "3:0.5" "4:0" "5:1"
## 3 "1:1"   "2:1"   "3:0"   "4:0" "5:1"
## 4 "1:1"   "2:1"   "3:0"   "4:0" "5:1"
## 5 "1:1"   "2:1"   "3:0"   "4:0" "5:1"

4voto

Richard Scriven Points 15577

Comme alternative à la boucle, vous pouvez utiliser col(., as.factor = TRUE) pour créer une matrice de noms de colonnes, puis la coller dans les données (coerced to matrix).

df[] <- paste(col(df, TRUE), as.matrix(df), sep = ":")

Résultant en :

      1     2     3   4   5
1   1:1 2:0.5 3:0.5 4:0 5:1
2 1:0.5 2:0.5 3:0.5 4:0 5:1
3   1:1   2:1   3:0 4:0 5:1
4   1:1   2:1   3:0 4:0 5:1
5   1:1   2:1   3:0 4:0 5:1

En fait, avec ces noms de colonnes particuliers, as.factor = TRUE n'est pas nécessaire. Mais il serait nécessaire pour les noms de colonnes qui ne sont pas les mêmes que les numéros de colonnes. Pour cet exemple particulier, cela pourrait être

df[] <- paste(col(df), as.matrix(df), sep = ":")

P.S. Vous devriez vraiment utiliser une matrice avec des données 100% numériques, au lieu d'un cadre de données.

Données :

df <- structure(list(`1` = c(1, 0.5, 1, 1, 1), `2` = c(0.5, 0.5, 1, 
1, 1), `3` = c(0.5, 0.5, 0, 0, 0), `4` = c(0L, 0L, 0L, 0L, 0L
), `5` = c(1L, 1L, 1L, 1L, 1L)), .Names = c("1", "2", "3", "4", 
"5"), class = "data.frame", row.names = c("1", "2", "3", "4", 
"5"))

1voto

akrun Points 148302

Nous pouvons unlist l'ensemble des données et paste avec des éléments répliqués du nom de la colonne

df[] <- paste(names(df)[col(df)], unlist(df), sep=":")
df
#      1     2     3   4   5
#1   1:1 2:0.5 3:0.5 4:0 5:1
#2 1:0.5 2:0.5 3:0.5 4:0 5:1
#3   1:1   2:1   3:0 4:0 5:1
#4   1:1   2:1   3:0 4:0 5:1
#5   1:1   2:1   3:0 4:0 5:1

données

df <- structure(list(`1` = c(1, 0.5, 1, 1, 1), `2` = c(0.5, 0.5, 1, 
1, 1), `3` = c(0.5, 0.5, 0, 0, 0), `4` = c(0L, 0L, 0L, 0L, 0L
), `5` = c(1L, 1L, 1L, 1L, 1L)), .Names = c("1", "2", "3", "4", 
 "5"), class = "data.frame", row.names = c("1", "2", "3", "4", 
 "5"))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X