J'ai une base de données des scores des étudiants, au lieu dePour obtenir un résultat moyen global pour chaque élève, je dois obtenir le résultat moyen par "type de cours" pour chaque élève. Par exemple, les cours a, c, d sont du même type et les cours b, e sont du même type. Je le fais par le code suivant, mais ce n'est pas assez "R":
x <- data.frame(a=c(1,2,3), b=c(4,5,6), c=c(6,7,8),
d=c(7,8,9), e=c(10, 11, 12))
group <- data.frame(no=c(1,2,1,1,2), name=c("a", "b", "c", "d","e"))
> x
a b c d e
1 1 4 6 7 10
2 2 5 7 8 11
3 3 6 8 9 12
> group
no name
1 1 a
2 2 b
3 1 c
4 1 d
5 2 e
Je pense que c'est un peu stupide:
x.1 <- x[,as.character(group$name[group$no==1])]
x.2 <- x[,as.character(group$name[group$no==2])]
mean.by.no <- data.frame(x.1.mean=apply(x.1, 1, mean),
x.2.mean=apply(x.2, 1, mean))
Réponses:
3 pour la réponse № 1Si mean.by.no
est le résultat attendu, nous pourrions split
la colonne "name" par "no" (ensemble de données "group") pour obtenir une liste. En utilisant l'un desapply
fonctions familiales (lapply/sapply/vapply
), nous pouvons utiliser la sortie comme index de colonne pour le "x" et obtenir la moyenne pour chaque ligne (rowMeans
).
vapply(with(group, split(as.character(name), no)),
function(y) rowMeans(x[y]), numeric(nrow(x)))
# 1 2
#[1,] 4.666667 7
#[2,] 5.666667 8
#[3,] 6.666667 9
Ou en utilisant tapply
, on peut avoir le mean
en utilisant l'index de regroupement pour la ligne et la colonne.
indx <- xtabs(no~name, group)[col(x)]
t(tapply(as.matrix(x), list(indx, row(x)), FUN=mean))
# 1 2
#1 4.666667 7
#2 5.666667 8
#3 6.666667 9
Ou une autre option serait de convertir le format "x" du format "large" au format "long" en utilisant melt
de data.table
après avoir converti "data.frame" en "data.table" (setDT
). Définissez la colonne clé comme "nom" (setkey(..
) et obtenez le mean
regroupés par "no" et "rn" (colonne de numéro de ligne créée par keep.rownames=TRUE
). Si nécessaire, la sortie peut être reconvertie au format "large" à l'aide de dcast
.
library(data.table)#v1.9.5+
dL <- setkey(melt(setDT(x, keep.rownames=TRUE), id.var="rn",
variable.name="name")[, name:= as.character(name)],
name)[group[2:1]][,mean(value) , by=list( no, rn)]
dcast(dL, rn~paste0("mean",no), value.var="V1")[,rn:=NULL][]
# mean1 mean2
#1: 4.666667 7
#2: 5.666667 8
#3: 6.666667 9
1 pour la réponse № 2
Il y a probablement une manière plus élégante de cela, mais:
library(reshape)
library(plyr)
x <- data.frame(a=c(1,2,3), b=c(4,5,6), c=c(6,7,8), d=c(7,8,9), e=c(10, 11, 12))
group <- data.frame(no=c(1,2,1,1,2), name=c("a", "b", "c", "d","e"))
a<-melt(x)
names(a)<-c("name", "score")
b<-merge(a, group, by="name")
c<-ddply(b, c("no"), summarize, meanscore=mean(score))
c
> c
no meanscore
1 1 5.666667
2 2 8.000000