148 votes

Pour chaque ligne, renvoyer le nom de la colonne de la valeur la plus grande.

Je dispose d'une liste d'employés et j'ai besoin de savoir dans quel département ils se trouvent le plus souvent. Il est trivial de tabuler l'ID de l'employé en fonction du nom du département, mais il est plus délicat de renvoyer le nom du département, plutôt que le nombre de comptages du fichier, à partir de la table de fréquence. Voici un exemple simple (noms des colonnes = départements, noms des lignes = ID des employés).

DF <- matrix(sample(1:9,9),ncol=3,nrow=3)
DF <- as.data.frame.matrix(DF)
> DF
  V1 V2 V3
1  2  7  9
2  8  3  6
3  1  5  4

Maintenant, comment puis-je obtenir

> DF2
  RE
1 V3
2 V1
3 V2

11voto

Gregor Sturm Points 758

A dplyr solution :

Idée :

  • ajouter les rowids comme une colonne
  • remodeler en format long
  • filtre pour le maximum dans chaque groupe

Code :

DF = data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,4))
DF %>% 
  rownames_to_column() %>%
  gather(column, value, -rowname) %>%
  group_by(rowname) %>% 
  filter(rank(-value) == 1) 

Résultat :

# A tibble: 3 x 3
# Groups:   rowname [3]
  rowname column value
  <chr>   <chr>  <dbl>
1 2       V1         8
2 3       V2         5
3 1       V3         9

Cette approche peut être facilement étendue pour obtenir le top n colonnes. Exemple pour n=2 :

DF %>% 
  rownames_to_column() %>%
  gather(column, value, -rowname) %>%
  group_by(rowname) %>% 
  mutate(rk = rank(-value)) %>%
  filter(rk <= 2) %>% 
  arrange(rowname, rk) 

Résultat :

# A tibble: 6 x 4
# Groups:   rowname [3]
  rowname column value    rk
  <chr>   <chr>  <dbl> <dbl>
1 1       V3         9     1
2 1       V2         7     2
3 2       V1         8     1
4 2       V3         6     2
5 3       V2         5     1
6 3       V3         4     2

3voto

Il s'agit d'une solution tidyverse simple et rapide, qui peut facilement être appliquée à n'importe quel sous-ensemble de colonnes dans un fichier de type data.frame . La version ci-dessous utilise également ifelse pour ajouter des valeurs manquantes si toutes les colonnes sont à 0. Les valeurs manquantes seraient utiles si, par exemple, quelqu'un voulait l'utiliser pour recombiner des colonnes codées à un coup. Il fonctionne sur les données de la question, mais voici un exemple d'un ensemble de données codées à un coup sur lequel il fonctionne également.

data <- data.frame(
   oh_a = c(1,0,0,1,0,0)
  ,oh_b = c(0,1,1,0,0,0)
  ,oh_c = c(0,0,0,0,1,0)
  ,d = c("l","m","n","o","p","q"))

f <- function(x){ifelse(rowSums(x)==0, NA, names(x)[max.col(x, "first")])}
data %>% 
  mutate(transformed = f(across(starts_with("oh"))))

sortie :

  oh_a oh_b oh_c d transformed
1    1    0    0 l        oh_a
2    0    1    0 m        oh_b
3    0    1    0 n        oh_b
4    1    0    0 o        oh_a
5    0    0    1 p        oh_c
6    0    0    0 q        <NA>

2voto

rar Points 611

Un simple for La boucle peut aussi être pratique :

> df<-data.frame(V1=c(2,8,1),V2=c(7,3,5),V3=c(9,6,4))
> df
  V1 V2 V3
1  2  7  9
2  8  3  6
3  1  5  4
> df2<-data.frame()
> for (i in 1:nrow(df)){
+   df2[i,1]<-colnames(df[which.max(df[i,])])
+ }
> df2
  V1
1 V3
2 V1
3 V2

0voto

In code veritas Points 595

Voici une réponse qui fonctionne avec data.table et qui est plus simple. Cela suppose que votre data.table s'appelle yourDF :

j1 <- max.col(yourDF[, .(V1, V2, V3, V4)], "first")
yourDF$newCol <- c("V1", "V2", "V3", "V4")[j1]

Remplacer ("V1", "V2", "V3", "V4") y (V1, V2, V3, V4) avec les noms de vos colonnes

0voto

SmokeyShakers Points 2075

Celui-ci est rapide :

with(DF, {
  names(DF)[(V1 > V2 & V1 > V3) * 1 + (V2 > V3 & V2 > V1) * 2 + (V3 > V1 & V3 > V2)*3]
})

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