【问题标题】:Applying user defined functions to a specific column of each dataframe in a list of dataframes?将用户定义的函数应用于数据框列表中每个数据框的特定列?
【发布时间】:2021-09-06 03:57:01
【问题描述】:

背景

大家好!我目前正在进行一个项目,该项目需要我通过模型残差的引导来估计研究内方差,然后计算每个样本的 SEE。此过程必须逐个模型完成。

我首先创建了一个数据框列表,这些数据框使用以下代码 list.meta<- split(new.meta, new.meta$model) 根据因子变量 model 进行拆分,其中每个数据框都包含与单个模型有关的数据。我在下面提供了一个可重现的示例,并将其限制为 3 个模型;但是我的完整数据集包含 13 个。从那里我有两个用户定义的函数:一个用于计算 SEE,另一个生成 1000 个引导样本,使用先前定义的 SEE 函数计算每个样本的 SEE。我在下面也提供了透明度。

用户定义函数

#Define SEE function 
SEE<- function(x){
  sqrt((sum(x)/(length(x)-2))^2)
}

#Define function for generating bootstrap samples and calculating SEE for each sample

Bootstrap<- function(x){
  int<- lapply(1:1000, function(i) sample(x, replace = T))
  Calc.SEE<- sapply(int, SEE)
}

其中 x 是给定数据框“i”中的 Residuals

数据

list(`1` = structure(list(Study = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Model = c(1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), Residuals = c(26.96774194, 24.35483871, 15.74193548, 15.70967742, 
13.22580645, 12.87096774, 11.77419355, 10.67741935, 10.58064516, 
8.548387097, 8, 5.548387097, 5.35483871, 5.322580645, 2.612903226, 
1.483870968, 1.225806452, 0.258064516)), row.names = c(NA, 18L
), class = "data.frame"), `2` = structure(list(Study = c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), Model = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L), Residuals = c(20.19354839, 16.5483871, 15.74193548, 
14.61290323, 7.064516129, 6.580645161, 5.64516129, 4.580645161, 
4.612903226, 3.612903226, 3.35483871, 2.741935484, 2.419354839, 
1.64516129, 1.35483871, 1.903225806, 0.516129032)), row.names = 19:35, class = "data.frame"), 
    `3` = structure(list(Study = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Model = c(3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L
    ), Residuals = c(23.80645161, 17.41935484, 15.58064516, 13.22580645, 
    11.32258065, 10.4516129, 6.709677419, 6.193548387, 5.741935484, 
    4.870967742, 4.322580645, 2.709677419, 2.677419355, 1.032258065, 
    1.129032258, 0.451612903, 1.064516129)), row.names = 36:52, class = "data.frame"))

问题/疑问

所以,这是我的问题:我需要将引导函数应用于每个模型的 residuals 列,输出最终是长度为 13 的列表(其中列表的每个元素都是由 1000 SEE 组成的向量值)或作为具有 13 列和 1000 行的数据框/矩阵(第二个更可取,因为它将用于进一步分析,并且包将数据框作为输入)。

我想最好的方法之一是通过for 循环或apply 系列中的一个函数。但是,就语法而言,当这些以列表格式嵌套时,我不知道如何将函数实际应用于每个数据帧的特定列

我的尝试

  1. 尝试一种方法是使用lapply 函数。
dat<- lapply(na.omit(new.data[[i]][, 4]), Bootstrap)

[[i]][, 4] 是我试图告诉 R 使用列表中第 i 个元素的第四列中的数据。这部分有效,但返回了长度为 18 的列表?一些列表元素也没有任何意义。

  1. 我正在研究的第二个选项是使用 for 循环:
for (i in 1:seq_along(new.data)){
result<- Bootstrap(new.data[[i]][,4])
return(result)
}

但这会返回错误

In 1:seq_along(new.data) :
  numerical expression has 13 elements: only the first used

我也不知道如何将结果实际保存为列表或矩阵格式,而我的 for 循环技能可能需要更多的工作......就是这样。

可能会有一个非常简单的答案,所以提前感谢您的任何和所有建议。我真的需要花时间练习编码:)

【问题讨论】:

    标签: r list dataframe for-loop user-defined-functions


    【解决方案1】:

    你可以的

    dat <- lapply(new.data, function(dataFrameInList) {
        Bootstrap(na.omit(dataFrameInList[["Residuals"]]))
    })
    

    我希望命名清晰易懂。在列表上使用lapply 时,它会抓取每个元素,在您的情况下,data.frames我将dataFrameInList 称为“循环变量”。然后,通过dataFrameInList[["Residuals"]] 选择残差。或者,您可以使用dataFrameInList[,"Residuals"]dataFrameInList[,4]。扔掉NAs,最后应用你的Bootstrap-function。

    【讨论】:

    • 效果很好,非常感谢!我决定将lapply 更改为sapply 以获取矩阵格式的数据。您的解释和命名非常清楚,但有几件事我不明白: 1. 为什么这行得通,但用[[i]][, 4] 索引却不行?我知道它会遍历每个元素,即data.frame 2。我知道该函数是所谓的“匿名”函数,但它是如何工作的?您能否再解释一下,因为我认为这将有助于我对未来问题的思考过程。再次,非常感谢。
    • 再次感谢您的所有帮助,乔纳斯。我现在已经能够在流程的每个阶段使用tapply 和匿名函数将流程简化为一个代码块。
    猜你喜欢
    • 1970-01-01
    • 2018-11-10
    • 2020-11-11
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 2020-10-28
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多