【问题标题】:Use index of a list of data.frames to apply a function in certain elements of a data frame使用 data.frames 列表的索引在数据框的某些元素中应用函数
【发布时间】:2013-07-03 21:41:47
【问题描述】:

我有一个data.frame,看起来像这样:

>df

  A B   C  P1  P2  P3  P4  P5  P6
1 a 1 0.1 0.1 0.1 0.4 0.2 0.1 0.4
2 b 1 0.2 0.1 0.4 0.2 0.1 0.2 0.2
3 c 1 0.4 0.4 0.1 0.2 0.1 0.1 0.4
4 d 2 0.1 0.1 0.7 0.5 0.1 0.7 0.1
5 e 2 0.5 0.7 0.5 0.1 0.7 0.1 0.5
6 f 2 0.7 0.5 0.5 0.7 0.1 0.7 0.1
7 g 3 0.1 0.1 0.1 0.2 0.2 0.2 0.5
8 h 3 0.2 0.2 0.1 0.5 0.2 0.2 0.5
9 i 3 0.5 0.1 0.2 0.1 0.1 0.5 0.2 

还有一个类似于这个的data.frames列表:

list.1 <- list(data.frame(AA=c("a","b","c","d")), 
             data.frame(BB=c("e","f")), 
             data.frame(CC=c("a","b","i")), 
             data.frame(DD=c("d","e","f","g")))

另外,我还有这个功能:

Fisher.test <- function(p) {
  Xsq <- -2*sum(log(p), na.rm=T)
  p.val <- 1-pchisq(Xsq, df = 2*length(p))
  return(p.val)
}

我想在df 中选择与列表中每个 data.frame 对应的 df$A 值,并为 P1...P6 计算 Fisher.test。我这样做的方式是将dflist.1 合并,然后将Fisher.method 应用于列表中的每个data.frame

func <- function(x,y){merge(x,y, by.x=names(x)[1], by.y=names(y)[1])}

ll <- lapply(list.1, func, df)

ll.fis <- lapply(ll, FUN=function(i){apply(i[,4:9],2,Fisher.test)})

这可行,但我的真实数据很大,所以我认为另一种方法可以使用list.1[1] 的元素索引来计算Fisher.testdf 存储结果,然后使用list.1[2] 的索引并计算Fisher.test 等等。通过这种方式,可以避免合并,因为所有计算都是在df 上进行的,而且这种方法也可以最大限度地减少 RAM 资源。但是,我不知道如何实现这一目标。也许是一个 for 循环?

谢谢

【问题讨论】:

  • data.table 是您的朋友。将key设置为A,然后使用lapply(list.1, function(x) DT[.(x), &lt;expression&gt;])

标签: r


【解决方案1】:

在此处利用 data.table 很有帮助,因为您可以使用 .( ) 语法轻松地对数据进行子集化,而且速度极快,尤其是与处理大数据相比,例如 subset

library(data.table)

# convert to data.table, setting the key to the column `A`
DT <- data.table(df, key="A")

p.col.names <- paste0("P", 1:6)
results <- lapply(list.1, function(ll)
        DT[.(ll)][, lapply(.SD, Fisher.test), .SDcols=p.col.names] )

results

旁注

您可能希望修复 list.1 的名称,以便正确命名结果表单 lapply

# fix the names, helpful for the lapply
names(list.1) <- lapply(list.1, names)

结果:

$AA
           P1        P2        P3       P4        P5      P6
1: 0.04770305 0.1624142 0.2899578 0.029753 0.1070376 0.17549

$BB
          P1        P2        P3        P4        P5        P6
1: 0.7174377 0.5965736 0.2561482 0.2561482 0.2561482 0.1997866

$CC
          P1       P2       P3         P4        P5        P6
1: 0.0317663 0.139877 0.139877 0.05305057 0.1620897 0.2189595

$DD
         P1        P2        P3        P4        P5        P6
1: 0.184746 0.4246214 0.2704228 0.1070376 0.3215871 0.1519672

【讨论】:

  • Fisher.test 是按列应用的吗?该函数应该只返回一个列的 pvalue....
  • @user2380782,请查看编辑。 (原始响应是按 A 中的每个值应用每列。编辑后的版本是每列。)
  • Ricardo,我试图修改上面的代码只是为了合并列表中的数据框,但我很可能做错了什么(我只是从data.table 开始)。你能看一下(github.com/abnova/diss-floss/blob/master/analysis/sem-models/…;第 160-161 行)吗?
  • 抱歉,Aleksandr,我对您的代码进行了顶峰,但这并不是很明显,很遗憾我没有时间筛选您的所有代码。我建议您自己尝试将问题归零,然后在此处发布后续(新)问题。
猜你喜欢
  • 1970-01-01
  • 2021-02-03
  • 2017-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
相关资源
最近更新 更多