如何按行将数据帧拆分为 n 个块,应用函数并组合?
how do I split a dataframe by row into chunks of n, apply a function and combine?
我有一个 data.frame
的 130,209 行。
> head(dt)
mLow1 mHigh1 mLow2 mHigh2 meanLow meanHigh fc mean
A_00001 37.00 12.75 99.25 78.50 68.125 45.625 1.4931507 56.8750
A_00002 31.00 21.50 84.75 53.00 57.875 37.250 1.5536913 47.5625
A_00003 72.50 26.50 81.75 74.75 77.125 50.625 1.5234568 63.8750
我想将 data.frame
拆分为 12,在 fc
列上应用 scale
函数,然后将其合并。这里没有分组变量,否则我会使用ddply
。另外,因为 130,209 不能被 12 完全整除,所以得到的 data.frames
将是不平衡的,即 11 data.frame
将有 10,851 行,最后一个将有 10,848 行,但这没关系。
那么如何将 data.frame
按行拆分为 n 个块(在本例中为 12 个),应用一个函数,然后将它们组合在一起?非常感谢任何帮助。
更新:
使用两个顶级解决方案,我得到不同的结果:
使用@Ben Bolker 的解决方案,
mLow1 mHigh1 mLow2 mHigh2 UID gene_id meanLow meanHigh mean fc
1.5 3.25 1 1.25 MGLibB_00021 0610010K14Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00034 0610037L13Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibB_00058 1100001G20Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00061 1110001A16Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00104 1110034G24Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00110 1110038F14Rik 1.25 2.25 1.75 -0.5231249
使用@MichaelChirico 的回答:
mLow1 mHigh1 mLow2 mHigh2 UID gene_id meanLow meanHigh mean fc fc_scaled
1.5 3.25 1 1.25 MGLibB_00021 0610010K14Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00034 0610037L13Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibB_00058 1100001G20Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00061 1110001A16Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00104 1110034G24Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00110 1110038F14Rik 1.25 2.25 1.75 0.5555556 -0.5089608
ggplot2
有一个 cut_number()
方便的功能可以为你做这件事。如果您不想加载该包的开销,您可以查看 ggplot2:::breaks
以了解必要的逻辑。
从@MichaelChirico 窃取的可重现示例:
set.seed(100)
KK<-130209L; nn<-12L
library("dplyr")
dt <- data.frame(mLow1=rnorm(KK),mHigh1=rnorm(KK),
mLow2=rnorm(KK),mHigh2=rnorm(KK),
meanLow=rnorm(KK),meanHigh=rnorm(KK),
fc=rnorm(KK),mean=rnorm(KK)) %>% arrange(mean)
对那些不喜欢管道的人表示歉意:
library("ggplot2") ## for cut_number()
dt %>% mutate(grp=cut_number(mean,12)) %>%
group_by(grp) %>%
mutate(fc=c(scale(fc))) %>%
ungroup() %>%
select(-grp) %>% ## drop grouping variable
as.data.frame -> dt2 ## convert back to data frame, assign result
事实证明 scale()
周围的 c()
是必要的——否则 fc
变量最终会带有一些混淆 tail()
的属性 ...
同样的逻辑也应该适用于使用 plyr
或基础 R split-apply-combine(关键是使用 cut_number()
来定义分组变量)。
使用 data.table
,您可以:
library(data.table)
setDT(dt)[,scale(fc),by=rep(1:nn,each=ceiling(KK/nn),length.out=KK)]
此处,KK
为130,209,nn
为12。可重现数据:
set.seed(100)
KK<-130209L; nn<-12L
dt<-data.frame(mLow1=rnorm(KK),mHigh1=rnorm(KK),
mLow2=rnorm(KK),mHigh2=rnorm(KK),
meanLow=rnorm(KK),meanHigh=rnorm(KK),
fc=rnorm(KK),mean=rnorm(KK))
因此无需拆分数据并重新组合。
如果您想将其添加到数据框中而不是仅仅提取它,您可以使用 :=
运算符通过引用分配:
setDT(dt)[,fc_scaled:=scale(fc)...]
我不确定 dt
的结构有那么重要(如果您没有使用它的任何内部值来进行拆分)。这有帮助吗?
spl.dt <- split( dt , cut(1:nrow(dt), 12) )
lapply( spl.dt, my_fun)
我有一个 data.frame
的 130,209 行。
> head(dt)
mLow1 mHigh1 mLow2 mHigh2 meanLow meanHigh fc mean
A_00001 37.00 12.75 99.25 78.50 68.125 45.625 1.4931507 56.8750
A_00002 31.00 21.50 84.75 53.00 57.875 37.250 1.5536913 47.5625
A_00003 72.50 26.50 81.75 74.75 77.125 50.625 1.5234568 63.8750
我想将 data.frame
拆分为 12,在 fc
列上应用 scale
函数,然后将其合并。这里没有分组变量,否则我会使用ddply
。另外,因为 130,209 不能被 12 完全整除,所以得到的 data.frames
将是不平衡的,即 11 data.frame
将有 10,851 行,最后一个将有 10,848 行,但这没关系。
那么如何将 data.frame
按行拆分为 n 个块(在本例中为 12 个),应用一个函数,然后将它们组合在一起?非常感谢任何帮助。
更新: 使用两个顶级解决方案,我得到不同的结果: 使用@Ben Bolker 的解决方案,
mLow1 mHigh1 mLow2 mHigh2 UID gene_id meanLow meanHigh mean fc
1.5 3.25 1 1.25 MGLibB_00021 0610010K14Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00034 0610037L13Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibB_00058 1100001G20Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00061 1110001A16Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00104 1110034G24Rik 1.25 2.25 1.75 -0.5231249
1.5 3.25 1 1.25 MGLibA_00110 1110038F14Rik 1.25 2.25 1.75 -0.5231249
使用@MichaelChirico 的回答:
mLow1 mHigh1 mLow2 mHigh2 UID gene_id meanLow meanHigh mean fc fc_scaled
1.5 3.25 1 1.25 MGLibB_00021 0610010K14Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00034 0610037L13Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibB_00058 1100001G20Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00061 1110001A16Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00104 1110034G24Rik 1.25 2.25 1.75 0.5555556 -0.5089608
1.5 3.25 1 1.25 MGLibA_00110 1110038F14Rik 1.25 2.25 1.75 0.5555556 -0.5089608
ggplot2
有一个 cut_number()
方便的功能可以为你做这件事。如果您不想加载该包的开销,您可以查看 ggplot2:::breaks
以了解必要的逻辑。
从@MichaelChirico 窃取的可重现示例:
set.seed(100)
KK<-130209L; nn<-12L
library("dplyr")
dt <- data.frame(mLow1=rnorm(KK),mHigh1=rnorm(KK),
mLow2=rnorm(KK),mHigh2=rnorm(KK),
meanLow=rnorm(KK),meanHigh=rnorm(KK),
fc=rnorm(KK),mean=rnorm(KK)) %>% arrange(mean)
对那些不喜欢管道的人表示歉意:
library("ggplot2") ## for cut_number()
dt %>% mutate(grp=cut_number(mean,12)) %>%
group_by(grp) %>%
mutate(fc=c(scale(fc))) %>%
ungroup() %>%
select(-grp) %>% ## drop grouping variable
as.data.frame -> dt2 ## convert back to data frame, assign result
事实证明 scale()
周围的 c()
是必要的——否则 fc
变量最终会带有一些混淆 tail()
的属性 ...
同样的逻辑也应该适用于使用 plyr
或基础 R split-apply-combine(关键是使用 cut_number()
来定义分组变量)。
使用 data.table
,您可以:
library(data.table)
setDT(dt)[,scale(fc),by=rep(1:nn,each=ceiling(KK/nn),length.out=KK)]
此处,KK
为130,209,nn
为12。可重现数据:
set.seed(100)
KK<-130209L; nn<-12L
dt<-data.frame(mLow1=rnorm(KK),mHigh1=rnorm(KK),
mLow2=rnorm(KK),mHigh2=rnorm(KK),
meanLow=rnorm(KK),meanHigh=rnorm(KK),
fc=rnorm(KK),mean=rnorm(KK))
因此无需拆分数据并重新组合。
如果您想将其添加到数据框中而不是仅仅提取它,您可以使用 :=
运算符通过引用分配:
setDT(dt)[,fc_scaled:=scale(fc)...]
我不确定 dt
的结构有那么重要(如果您没有使用它的任何内部值来进行拆分)。这有帮助吗?
spl.dt <- split( dt , cut(1:nrow(dt), 12) )
lapply( spl.dt, my_fun)