1
votes

Somme des colonnes voisines en fonction des conditions

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!

r sum

0 commentaires

3 Réponses :


0
votes

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:

  1. Il utilise un "sentinel" 0 à la fin de son argument pour garantir que which.min renvoie une valeur non vide.

  2. 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.


0 commentaires

0
votes

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))


0 commentaires

1
votes

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]))


2 commentaires

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