我有一个data.frame,如下所示,其中location
是一个因素而sample
是一些测量样本:
location sample
1 'A' 0.10
2 'A' 0.20
3 'A' 0.15
4 'B' 0.15
5 'B' 0.99
6 'B' 0.54
...
我有一个函数ECCDFpts(df)
,其中df
是一个data.frame,它在<x,y>
的经验CCDF上返回一组df$sample
点,如下所示:
x y
1 0.0 1.00
2 0.1 0.99
3 0.2 0.75
...
请注意,返回的<x,y>
点数是“任意”。 不输入样本与输出<x,y>
行之间的一对一映射。
我想在每个因子(例如,位置)的基础上计算这个CCDF数据,产生这样的data.frame:
location x y
1 'A' 0.0 1.0
2 'A' 0.1 1.0
3 'A' 0.2 0.3
4 'B' 0.0 1.0
5 'B' 0.1 1.0
6 'B' 0.2 0.7
...
我目前的做法是将初始数据框拆分为因子location
:
eccdfs_by_factor <- by(data, data$location, ECCDFpts)
这会产生data.frames列表:
data$location: A
x y
1 0.0 1.0
2 0.1 1.0
3 0.2 0.3
-----------------
data$location: B
x y
1 0.0 1.0
2 0.1 1.0
3 0.2 0.7
我不知道如何合并或取消将其重新分成我想要的形式,如前所示。我想合并,以便列表中的元素名称(data.frames)成为组合data.frame中的列因子。
解决方案:
显然,这是一个典型的分裂 - 应用 - 组合问题。最干净的solutions below使用plyr
包函数ddply(...)
来进行拆分,应用和组合在一行中!我不需要上面使用的基本by
函数。
答案 0 :(得分:4)
更新:如果我理解你想要的东西......
library(plyr)
ldply(your_data)
例如:
x <- list(a=data.frame(x=c(1,2,3,4),y=c(2,3,4,5)),
b=data.frame(x=c(4,3,2,1),y=c(5,4,3,2)))
ldply(x)
.id x y
1 a 1 2
2 a 2 3
3 a 3 4
4 a 4 5
5 b 4 5
6 b 3 4
7 b 2 3
8 b 1 2
答案 1 :(得分:3)
一次性解决方案使用plyr
包。由于我不知道您的ECDFpts功能,我将自己编写以说明其用法。
# DEFINE DUMMY DATA
mydata = data.frame(
location = rep(LETTERS[1:3], each = 3),
sample = runif(9)
)
# DEFINE DUMMY FUNCTION
myfunc = function(dat){
x = dat - mean(dat)
y = dat - median(dat)
return(data.frame(x, y))
}
# USE PLYR TO APPLY FUNCTION BY LOCATION
library(plyr)
ans = ddply(mydata, .(location), transform, x = myfunc(sample)$x,
y = myfunc(sample)$y)
location sample x y
1 A 0.911 0.3279 0.232
2 A 0.678 0.0958 0.000
3 A 0.159 -0.4237 -0.520
4 B 0.908 0.3096 0.048
5 B 0.860 0.2615 0.000
6 B 0.027 -0.5711 -0.833
7 C 0.745 0.0694 0.000
8 C 0.343 -0.3327 -0.402
9 C 0.939 0.2633 0.194
EDIT。正如@David在评论中所指出的那样,代码可以进一步简化为
# DEFINE DUMMY FUNCTION
myfunc = function(dat){
x = with(dat, sample - mean(sample))
y = with(dat, sample - median(sample))
return(data.frame(x, y))
}
ans = ddply(mydata, .(location), myfunc)
location x y
1 A -0.0308 -0.00564
2 A -0.0251 0.00000
3 A 0.0559 0.08102
4 B -0.4985 -0.69084
5 B 0.3062 0.11392
6 B 0.1923 0.00000
7 C -0.2894 -0.31495
8 C 0.0255 0.00000
9 C 0.2639 0.23838
答案 2 :(得分:3)
您收到的答案绰绰有余,但为了完整起见,我想添加一个解决方案,解释如何从by
命令的输出开始获得所需的结果。我将使用一个稍微修改过的Ramnath示例来说明:
mydata = data.frame(
location = rep(LETTERS[1:3], each = 3),
sample = runif(9)
)
# DEFINE DUMMY FUNCTION - slightly different from ramnath's
myfunc = function(dat){
temp <- data.frame(x = runif(3), y = rnorm(3))
return(temp)
}
您按location
分割数据并使用by
应用您的功能:
rs <- by(mydata,mydata$location,FUN = myfunc)
mydata$location: A
x y
1 0.2730105 -0.06923224
2 0.9354096 -0.18336131
3 0.6359926 -0.04054326
-----------------------------------------------------------
mydata$location: B
x y
1 0.5621529 -0.26404739
2 0.8098687 0.07912883
3 0.7334650 0.38287794
-----------------------------------------------------------
mydata$location: C
x y
1 0.8443924 -0.9055125
2 0.7922256 0.1757586
3 0.4923929 -0.1931579
现在,一个非常方便的事情是,我们可以使用do.call
和rbind
重新将所有内容重新组合在一起:
result <- do.call(rbind,rs)
x y
A.1 0.2730105 -0.06923224
A.2 0.9354096 -0.18336131
A.3 0.6359926 -0.04054326
B.1 0.5621529 -0.26404739
B.2 0.8098687 0.07912883
B.3 0.7334650 0.38287794
C.1 0.8443924 -0.90551251
C.2 0.7922256 0.17575858
C.3 0.4923929 -0.19315789
但是等等,你说!添加我的位置列怎么样?那么,请注意do.call(rbind,rs)
对结果的行名称所做的事情!我们可以通过从行名称中提取第一个字符来添加位置列:
result$location <- substr(row.names(result),1,1)
当然,这假定您的位置使用单个字符进行编码。但一般来说,生成的行名称应采用location.x
形式,因此您可以始终使用strsplit
或正则表达式来提取位置名称。
最后,您可以随时修改应用于每个部分的功能,以便在返回结果之前将位置名称添加为列,如下所示:
#Output not shown
myfunc1 = function(dat){
temp <- data.frame(x = runif(3), y = rnorm(3))
temp$location <- dat$location[1]
return(temp)
}
rs1 <- by(mydata,mydata$location,FUN = myfunc1)
result1 <- do.call(rbind,rs1)
所以你只需要以类似的方式修改你的ECCDFpts
功能。