2015-03-03 2 views
2

J'ai piraté ensemble une solution rapide à mon problème, mais j'ai le sentiment qu'il est assez obtus. En outre, il utilise pour les boucles, qui, d'après ce que j'ai compris, devrait être évité à tout prix dans R. Tous les conseils pour ranger ce code est apprécié. Je suis encore assez nouveau à R, mais je crains de faire un problème relativement simple et trop compliqué.Boucle ou appliquer pour la somme des lignes en fonction de plusieurs conditions dans R dataframe

J'ai un ensemble de données comme suit:

id count group 
2 6 A 
2 8 A 
2 6 A 
8 5 A 
8 6 A 
8 3 A 
10 6 B 
10 6 B 
10 6 B 
11 5 B 
11 6 B 
11 7 B 
16 6 C 
16 2 C 
16 0 C 
18 6 C 
18 1 C 
18 6 C 

Je voudrais créer une nouvelle trame de données qui contient, pour chaque ID unique, la somme des deux premiers chefs d'accusation de cette identité (par exemple 6 + 8 = 14 pour ID 2). Je veux également attacher l'identifiant de groupe correct.

En général, vous devrez peut-être effectuer cette opération lorsque vous mesurerez une valeur sur plusieurs jours consécutifs pour différents sujets et traitements, et que vous souhaitez calculer le total de chaque sujet pour les x premiers jours de mesure.

C'est ce que je suis venu avec:

id <- c(rep(c(2,8,10,11,16,18),each=3)) 
count <- c(6,8,6,5,6,3,6,6,6,5,6,7,6,2,0,6,1,6) 
group <- c(rep(c("A","B","C"),each=6)) 
df <- data.frame(id,count,group) 

newid<-c() 
newcount<-c() 
newgroup<-c() 
for (i in 1:length(unique(df$"id"))) { 
    newid[i] <- unique(df$"id")[i] 
    newcount[i]<-sum(df[df$"id"==unique(df$"id")[i],2][1:2]) 
    newgroup[i] <- as.character(df$"group"[df$"id"==newid[i]][1]) 
} 

newdf<-data.frame(newid,newcount,newgroup) 

Quelques améliorations/alternatives possibles, je ne suis pas sûr:

  • Pour boucles vs appliquer des fonctions
  • Puis-je créer une trame de données directement à l'intérieur d'une boucle for ou devrais-je m'en tenir à créer des vecteurs que je peux attribuer en retard à une trame de données?
  • Des approches plus cohérentes à l'accès/vecteurs/de colonnes sous- ensembles (de $, [], [[]], sous-ensemble?)

Répondre

1

Vous pouvez le faire en utilisant data.table

setDT(df)[, list(newcount = sum(count[1:2])), by = .(id, group)] 
# id group newcount 
#1: 2  A  14 
#2: 8  A  11 
#3: 10  B  12 
#4: 11  B  11 
#5: 16  C  8 
#6: 18  C  7 
1

Vous pouvez essayer d'utiliser une fonction d'auto-définie dans son ensemble

sum1sttwo<-function (x){ 
    return(x[1]+x[2]) 
} 
aggregate(count~id+group, data=df,sum1sttwo) 

et la sortie est:

id group count 
1 2  A 14 
2 8  A 11 
3 10  B 12 
4 11  B 11 
5 16  C  8 
6 18  C  7 

04/2015 modifier: dplyr et data.table sont des choix certainement mieux lorsque votre ensemble de données est grande. L'un des inconvénients les plus importants de la base R est que la trame de données est trop lente. Cependant, si vous avez juste besoin d'agréger un ensemble de données très simple/petit, la fonction d'agrégat dans la base R peut remplir son objectif.

0
library(plyr) 

    -Keep first 2 rows for each group and id 
    df2 <- ddply(df, c("id","group"), function (x) x$count[1:2]) 

    -Aggregate by group and id 
    df3 <- ddply(df2, c("id", "group"), summarize, count=V1+V2) 

    df3 
    id group count 
    1 2  A 14 
    2 8  A 11 
    3 10  B 12 
    4 11  B 11 
    5 16  C  8 
    6 18  C  7 
1

Vous pouvez utiliser dplyr:

library(dplyr) 
df %>% group_by(id,group) %>% slice(1:2) %>% summarise(newcount=sum(count)) 

La syntaxe de la conduite, il est facile à lire: regrouper vos données par id et group, prennent les deux premières lignes pour chaque groupe, puis additionnez le counts