我有一个包含四列的数据框df
,例如
A B C D
x a 1 3
x a 3 4
x b 5 5
x b 6 8
y a 6 5
y a 8 9
y b 7 0
y b 4 2
我希望按列A和B聚合此数据框,然后为列C和D上的每个组应用函数。一个此类函数可能是cor
,另一个lm
。结果应该看起来像
A B cor/lm.coef
x a ...
x b ...
y a ...
y b ...
我找到了一种接近所需结果的方法:通过函数by
:
by(df, c("A", "B"), function(x) cor(x$C, x$D))
by(df, c("A", "B"), function(x) lm(C ~ D, data = x))
我的问题:我是否可以将所需结果作为cor
的新数据框提取出来。 lm.coef
由A列和B列的因子编制索引?如何访问by
的结果对象?还有另一种方法可以获得理想的结果吗?
答案 0 :(得分:3)
我不是by()
的忠实粉丝。我使用split()
和lapply()
处理此任务。
do.call(rbind, lapply(split(df, list(df$A, df$B)),
function(d) {
l <- lm(C~D, data=d)$coef
data.frame(A=d$A[1], B=d$B[1], COR=cor(d$C, d$D), LM1=l[1], LM2=l[2])
}
))
这给出了:
A B COR LM1 LM2
x.a x a 1 -5.000000 2.0000000
y.a y a 1 3.500000 0.5000000
x.b x b 1 3.333333 0.3333333
y.b y b -1 7.000000 -1.5000000
顺便说一下,by()
返回的对象实际上是一个矩阵:
x <- by(df, list(df$A, df$B), function(x) cor(x$C, x$D))
unclass(x)
# a b
# x 1 1
# y 1 -1
这可能会为您提供有关如何进一步处理它的提示。
答案 1 :(得分:2)
只是为了补充@gagolews答案,这是一个dplyr
版本
txt <- 'A B C D
x a 1 3
x a 3 4
x b 5 5
x b 6 8
y a 6 5
y a 8 9
y b 7 0
y b 4 2'
df <- read.table(text = txt, header = TRUE)
library(dplyr)
df %>%
group_by(A, B) %>%
do(mod = lm(C ~ D, data = .), cor = with(., cor(C, D))) %>%
do(data_frame(
A = .$A,
B = .$B,
cor = .$cor,
lm1 = coef(.$mod)[1],
lm2 = coef(.$mod)[2])
)
## A B cor lm1 lm2
## 1 x a 1 -5.0000 2.00000
## 2 x b 1 3.3333 0.33333
## 3 y a 1 3.5000 0.50000
## 4 y b -1 7.0000 -1.50000
答案 2 :(得分:2)
data.table
方法是:
require(data.table)
setDT(df)
df[,c(as.list(coef(lm(C~D))), list(cor = cor(C, D))), by=.(A,B)]
c
用于合并/集中两个列表:as.list(coef(...))
和list(cor = ...)
。 data.table
automaticalls使它们成为列。
结果:
A B (Intercept) D cor
1: x a -5.000000 2.0000000 1
2: x b 3.333333 0.3333333 1
3: y a 3.500000 0.5000000 1
4: y b 7.000000 -1.5000000 -1
答案 3 :(得分:1)
# Expanding on your solution
x2<-df
#your code
mycor<-with(x2,by(x2[,3:4],interaction(A,B),cor))
myreg<-with(x2,by(x2,interaction(A,B),function(x)lm(C~D,data=x)))
#extra line
myreg_coef<-do.call(rbind,lapply(unique(interaction(x2$A,x2$B)),
function(x) cbind(group=x,corr=mycor[[x]][2],t(data.frame(myreg[[x]][1])))))