J'essaie de résumer les valeurs dans exactement quatre colonnes voisines en commençant par la colonne où j'ai la première valeur sur zéro. C'est à dire. lorsque la valeur de la colonne x1 est 0 et la valeur de x2 est 1, alors je veux avoir la somme de x2, x3, x4, x5. Supposons l'exemple suivant:
x1 x2 x3 x4 x5 x6 Sum 1 0 1 3 3 3 5 0 3 2 4 3 4 12 0 0 2 4 3 5 14
Dans la première ligne, la somme doit commencer par la première valeur car il s'agit de la première valeur supérieure à zéro de la ligne. Ensuite, il devrait prendre les quatre colonnes consécutives, donc x1 + x2 + x3 + x4. Dans la deuxième ligne, la somme doit commencer par la deuxième valeur, donc la somme serait x2 + x3 + x4 + x5. Dans la troisième ligne, la somme doit commencer par x3, conduisant à x3 + x4 + x5 + x6.
Donc, ce que je veux obtenir à la fin est une colonne avec les quatre sommes consécutives:
df<- data.frame(x1=c(1,0,0), x2=c(0,3,0), x3=c(1,2,2), x4=c(3,4,4), x5=c(3,3,3), x6=c(3,4,5)) x1 x2 x3 x4 x5 x6 1 0 1 3 3 3 0 3 2 4 3 4 0 0 2 4 3 5
Comme j'ai près de 40 colonnes et 300 lignes, je apprécierait vraiment une manière élégante de le faire.
Merci beaucoup!
3 Réponses :
La famille de fonctions qui
identifiera le premier différent de zéro. Il existe différentes manières de boucler: regardez la famille * apply
.
Voici une solution testée.
x1 x2 x3 x4 x5 x6 Sum 1 1 0 1 3 3 3 5 2 0 3 2 4 3 4 12 3 0 0 2 4 3 5 14
f <- function(x) { i <- which.min(c(x,0)==0) sum(x[i+0:3], na.rm=TRUE) } # # Test f. # stopifnot(mapply(function(x,y) f(x)==y, list(c(), 0, 1, c(1,NA), c(1,1), NA), c(0,0,1,1,2,0))) # # Do the calculation. # df<- data.frame(x1=c(1,0,0), x2=c(0,3,0), x3=c(1,2,2), x4=c(3,4,4), x5=c(3,3,3), x6=c(3,4,5)) df$Sum <- apply(df, 1, f) (df)
La fonction principale f
repose sur deux techniques à noter:
Il utilise un "sentinel" 0 à la fin de son argument pour garantir que which.min
renvoie une valeur non vide.
Il repose sur R
renvoyant des valeurs NA
pour les index au-delà de la plage valide. Ceux-ci sont expressément ignorés lors de l'appel suivant à sum
.
Vous devrez modifier f
si vous voulez qu'une sorte d'erreur ou d'avertissement soit renvoyée lorsqu'il n'y a pas au moins quatre valeurs dans une ligne à additionner.
Enfin, le test unitaire stopifnot
passe une liste d'arguments de test à f
(la plupart d'entre eux des «cas de bord») et une liste des valeurs prévues pour ces cas. Il applique f
à chacun de ces arguments et compare son résultat à la valeur voulue. En cas de divergence, R
arrêtera l'exécution. Cela vous permet d’obtenir les résultats souhaités.
Voici une option avec max.col
pour trouver la position de la colonne de la première valeur non nulle dans chaque ligne, créer la ligne
et la colonne code> index ('i', 'j') en utilisant
rep
, extrayez les valeurs dans l'ensemble de données et obtenez la somme
groupée par la colonne 'i' XXX données
df <- structure(list(x1 = c(1, 0, 0), x2 = c(0, 3, 0), x3 = c(1, 2,
2), x4 = c(3, 4, 4), x5 = c(3, 3, 3), x6 = c(3, 4, 5)),
class = "data.frame", row.names = c(NA,
-3L))
Peut-être que vous pouvez utiliser le code suivant
df <- structure(list(x1 = c(1, 0, 0), x2 = c(0, 3, 0), x3 = c(1, 2,2), x4 = c(3, 4, 4), x5 = c(3, 3, 3), x6 = c(3, 4, 5)), class = "data.frame", row.names = c(NA, -3L))
qui donne:
> df x1 x2 x3 x4 x5 x6 Sum 1 1 0 1 3 3 3 5 2 0 3 2 4 3 4 12 3 0 0 2 4 3 5 14
DATA p >
df$Sum <- sapply(1:nrow(df), function(k) sum(df[k,head(which(df[k,]>0),1) + 0:3]))
Merci pour votre solution. Cela a également fonctionné avec mon ensemble de données d'origine. Puis-je sélectionner des colonnes spécifiques dans votre code? Parce que je ne veux pas prendre en compte toutes mes colonnes pour le calcul (par exemple, les colonnes pour les noms doivent être ignorées). Ou puis-je résoudre ce problème uniquement en créant un sous-ensemble en sélectionnant uniquement les colonnes avec des nombres?
@ZayzayR Eh bien, je pense qu'il est préférable de sous-définir les colonnes que vous souhaitez utiliser, puis d'appliquer le code sur les colonnes sélectionnées. Sinon, l'intégration de la procédure de sélection de colonne augmentera la complexité du code, et pas aussi simple pour le traitement