R:将 lapply 与作用于拆分数据帧的一部分的函数一起使用
R: Use lapply with a function acting on part of a split dataframe
此 R 代码正在设置我试图解决的问题的示例。该数据集测量粒子在非均匀时间间隔内的释放。使用梯形法则随时间对粒子释放进行积分。
library(caTools)
test.data.frame <- data.frame(
sample = c('sample 1','sample 1','sample 1','sample 1',
'sample 2','sample 2','sample 2','sample 2'))
test.data.frame$time <- c(1,2,4,6,1,4,5,6)
test.data.frame$material.released.g <- c(5,3,2,1,2,4,5,1)
split.test <- split(test.data.frame, test.data.frame$sample)
integrate.test <- function(x){
dataframe.segment <- do.call(rbind.data.frame,x)
return(trapz(dataframe.segment$time,dataframe.segment$material.released.g))
}
到目前为止,integrate.test 函数似乎只作用于列表的单个元素。
> integrate.test(split.test[1])
[1] 12
> integrate.test(split.test[2])
[1] 16.5
lapply 函数在输出中给出零。
> lapply(split.test, integrate.test)
$`sample 1`
[1] 0
$`sample 2`
[1] 0
我正在寻找的输出是一个数据框,相当于:
expected.output <- data.frame(
sample = c('sample 1','sample 2'),
total.material.released = c(12 , 16.5))
有谁能帮忙解决错误代码。谢谢!
这是包含数据框的单元素列表split.test[1]
和存储在列表元素[[1]]中的数据框split.test[[1]]
的区别。
您的函数通过调用 do.call(rbind.data.frame, x)
,期望 x
是一个列表。但是 lapply(split.test, integrate.test)
实际上为它提供了一个数据框。以下是当您输入 integrate.test
数据框而不是(通用)列表时会发生的情况:
x = do.call(rbind.data.frame, split.test[[1]])
x
c.1..1..5. c.1..2..3. c.1..4..2. c.1..6..1.
sample 1 1 1 1
time 1 2 4 6
material.released.g 5 3 2 1
do.call
对列表进行操作。如果您为它提供一个通用列表(如 split.test[1]
,这是一个单元素列表),它会尝试 rbind
每个列表元素。如果列表包含多个数据框,它将把它们堆叠成一个数据框。但是只有一个元素——split.test
的元素 1 中包含的数据框——所以这就是返回的内容。
但是,当您 运行 do.call(rbind, split.test[[1]])
时,您是在给 do.call
一个要操作的数据框。数据框是一种特殊的列表,其中每一列都是一个列表元素。所以 do.call
获取原始数据框的列,将它们转置为行并堆叠它们。积分returns0,因为它要操作的列已经不存在了。当您引用那些不存在的列时,将返回 NULL
的值而不是您期望的数据,并且 trapz(NULL, NULL)
为零。
如果您直接使用数据框并跳过 do.call
步骤,该函数将起作用:
integrate.test <- function(x){
#dataframe.segment <- do.call(rbind.data.frame,x)
dataframe.segment = x
return(trapz(dataframe.segment$time,dataframe.segment$material.released.g))
}
lapply(split.test, integrate.test)
$`sample 1`
[1] 12
$`sample 2`
[1] 16.5
当然可以缩短为:
integrate.test <- function(x){
return(trapz(x$time,x$material.released.g))
}
或者您可以直接使用 trapz
,而不用将其包装在函数中。
此 R 代码正在设置我试图解决的问题的示例。该数据集测量粒子在非均匀时间间隔内的释放。使用梯形法则随时间对粒子释放进行积分。
library(caTools)
test.data.frame <- data.frame(
sample = c('sample 1','sample 1','sample 1','sample 1',
'sample 2','sample 2','sample 2','sample 2'))
test.data.frame$time <- c(1,2,4,6,1,4,5,6)
test.data.frame$material.released.g <- c(5,3,2,1,2,4,5,1)
split.test <- split(test.data.frame, test.data.frame$sample)
integrate.test <- function(x){
dataframe.segment <- do.call(rbind.data.frame,x)
return(trapz(dataframe.segment$time,dataframe.segment$material.released.g))
}
到目前为止,integrate.test 函数似乎只作用于列表的单个元素。
> integrate.test(split.test[1])
[1] 12
> integrate.test(split.test[2])
[1] 16.5
lapply 函数在输出中给出零。
> lapply(split.test, integrate.test)
$`sample 1`
[1] 0
$`sample 2`
[1] 0
我正在寻找的输出是一个数据框,相当于:
expected.output <- data.frame(
sample = c('sample 1','sample 2'),
total.material.released = c(12 , 16.5))
有谁能帮忙解决错误代码。谢谢!
这是包含数据框的单元素列表split.test[1]
和存储在列表元素[[1]]中的数据框split.test[[1]]
的区别。
您的函数通过调用 do.call(rbind.data.frame, x)
,期望 x
是一个列表。但是 lapply(split.test, integrate.test)
实际上为它提供了一个数据框。以下是当您输入 integrate.test
数据框而不是(通用)列表时会发生的情况:
x = do.call(rbind.data.frame, split.test[[1]])
x
c.1..1..5. c.1..2..3. c.1..4..2. c.1..6..1. sample 1 1 1 1 time 1 2 4 6 material.released.g 5 3 2 1
do.call
对列表进行操作。如果您为它提供一个通用列表(如 split.test[1]
,这是一个单元素列表),它会尝试 rbind
每个列表元素。如果列表包含多个数据框,它将把它们堆叠成一个数据框。但是只有一个元素——split.test
的元素 1 中包含的数据框——所以这就是返回的内容。
但是,当您 运行 do.call(rbind, split.test[[1]])
时,您是在给 do.call
一个要操作的数据框。数据框是一种特殊的列表,其中每一列都是一个列表元素。所以 do.call
获取原始数据框的列,将它们转置为行并堆叠它们。积分returns0,因为它要操作的列已经不存在了。当您引用那些不存在的列时,将返回 NULL
的值而不是您期望的数据,并且 trapz(NULL, NULL)
为零。
如果您直接使用数据框并跳过 do.call
步骤,该函数将起作用:
integrate.test <- function(x){
#dataframe.segment <- do.call(rbind.data.frame,x)
dataframe.segment = x
return(trapz(dataframe.segment$time,dataframe.segment$material.released.g))
}
lapply(split.test, integrate.test)
$`sample 1` [1] 12 $`sample 2` [1] 16.5
当然可以缩短为:
integrate.test <- function(x){
return(trapz(x$time,x$material.released.g))
}
或者您可以直接使用 trapz
,而不用将其包装在函数中。