4 votes

Créer des groupes sur la base de la combinaison des colonnes remplies non nulles

J'ai du mal à résoudre ce problème. Je vais l'expliquer au mieux sur la base de l'exemple, regardons les données ci-dessous :

    order type_a type_b type_c type_d
1     1      0     50     10      0
2     2     10      0      0     80
3     3     15      0      0     35
4     4      0      0     30      0
5     5      0     20     40      0

et dput :

data <- structure(list(order = c(1, 2, 3, 4, 5), type_a = c(0, 10, 15, 
0, 0), type_b = c(50, 0, 0, 0, 20), type_c = c(10, 0, 0, 30, 
40), type_d = c(0, 80, 35, 0, 0)), .Names = c("order", "type_a", 
"type_b", "type_c", "type_d"), row.names = c(NA, -5L), class = "data.frame")

Nous pouvons voir que la première colonne indique le numéro de commande, les autres colonnes indiquent ce que nous faisons. appartient à cette ordonnance. En outre, si la colonne type_* est remplie avec 0, elle n'est pas pertinente.

J'aimerais créer une nouvelle colonne qui définit des groupes basés sur les colonnes "description de la commande" --> type_*. Par exemple, pour la commande 1 et la commande 5, nous avons les mêmes colonnes type_* remplies avec aucune valeur 0, donc elles appartiennent au même groupe, de même pour les commandes 2 et 3, etc.

Mon résultat final devrait ressembler à ceci :

   order type_a type_b type_c type_d   group
1     1      0     50     10      0 group_1
2     2     10      0      0     80 group_2
3     3     15     10      0     35 group_2
4     4      0      0     30      0 group_3
5     5      0     20     40      0 group_1

Pour votre information, dans mes données réelles, j'ai plus de 4 colonnes type_* --> il y en a environ 10-15 !

Merci de votre aide !

8voto

Spacedman Points 33792

Vos groupes sont définis par la présence ou l'absence de 0 dans les colonnes 2 à 5. Testez la présence de 0, regroupez les valeurs VRAI/FAUX sous forme de chaîne et vous obtenez une chaîne unique pour chaque groupe. Convertissez en facteur :

> data$group = factor(apply(data[,2:5] ==0,1,paste,collapse=""))
> data
  order type_a type_b type_c type_d              group
1     1      0     50     10      0 TRUEFALSEFALSETRUE
2     2     10      0      0     80 FALSETRUETRUEFALSE
3     3     15      0      0     35 FALSETRUETRUEFALSE
4     4      0      0     30      0  TRUETRUEFALSETRUE
5     5      0     20     40      0 TRUEFALSEFALSETRUE

Maintenant que les noms sont laids, il faut changer les niveaux :

> class(data$group)
[1] "factor"
> levels(data$group)=paste("group_",1:length(levels(data$group)))
> data
  order type_a type_b type_c type_d    group
1     1      0     50     10      0 group_ 2
2     2     10      0      0     80 group_ 1
3     3     15      0      0     35 group_ 1
4     4      0      0     30      0 group_ 3
5     5      0     20     40      0 group_ 2

Si tous ces TRUEFALSE majuscules vous font mal aux yeux, un simple correctif vous permettra d'obtenir un nombre binaire net :

> data$group = factor(apply(0+(data[,2:5] ==0),1,paste,collapse=""))
> data
  order type_a type_b type_c type_d group
1     1      0     50     10      0  1001
2     2     10      0      0     80  0110
3     3     15      0      0     35  0110
4     4      0      0     30      0  1101
5     5      0     20     40      0  1001

2voto

Wimpel Points 3380

Solution data.table

library(data.table)

setDT(data)[, id := .GRP, by = list( do.call(paste0, c( data.frame( data[,2:5] != 0 ) ) ) ) ][, id := paste0( "Group_", id)][]

#    order type_a type_b type_c type_d      id
# 1:     1      0     50     10      0 Group_1
# 2:     2     10      0      0     80 Group_2
# 3:     3     15      0      0     35 Group_2
# 4:     4      0      0     30      0 Group_3
# 5:     5      0     20     40      0 Group_1

1voto

Brandon Bertelsen Points 13424

Cela pourrait échouer dans certaines situations, mais c'est une réponse amusante car nous pouvons utiliser R pour ce pour quoi il a été conçu. La programmation statistique.

set.seed(42)
cols <- grep("type_", names(d))
d$group <- kmeans(d[cols], 4)$cluster
# d$group <- paste0("group_", d$group)

La nature du regroupement k-means est telle que les colonnes "toujours" 0 ont tendance à avoir un fort effet de catégorisation sur les résultats.

Notes :

1) Nous utilisons grep pour identifier les colonnes, car l'utilisation de références numériques pour les noms de colonnes entraîne des problèmes à l'avenir si vos données n'ont pas la même forme ou si elles changent de position. C'est également plus lisible pour quelqu'un d'autre qui révise votre code.

2) Il faut éviter d'utiliser le nom de la variable data car il s'agit d'une fonction de la base R.

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