从数据帧列表中提取数据帧并执行计算

问题描述:

我在数据帧rand_sample中有一列是数据帧列表。我想只提取数据帧到数据帧中进行计算,然后再添加这些计算作为新列在rand_sample从数据帧列表中提取数据帧并执行计算

str(rand_sample[1, ]$times) 
List of 1 
$ :'data.frame': 13 obs. of 2 variables: 
    ..$ white: num [1:13] 1800 1834 1875 1897 1887 ... 
    ..$ black: num [1:13] 1800 1860 1946 2031 2114 ... 

一是指数看起来是这样的:

> rand_sample[1:10,]$times 
[[1]] 
    white black 
1 1800 1800 
2 1834 1860 
3 1875 1946 
4 1897 2031 
5 1887 2114 
6 1839 2203 
7 1835 2282 
8 1880 2370 
9 1875 2400 
10 1892 2323 
11 1612 2356 
12 1622 2370 
13 1619 2370 

从本质上讲,我想

for (i in 1:nrow(rand_sample)) { 
    current <- rand_sample[i, ]$times[[1]] 
    mW <- abs(diff(current$white)) 
    mB <- abs(diff(current$black)) 
    maxWhite <- max(mW) 
    minWhite <- min(mW) 
    maxBlack <- max(mB) 
    minBlack <- min(mB) 
    sdWhite <- sd(mW) 
    sdBlack <- sd(mB) 
    avgW <- mean(mW) 
    avgB <- mean(mB) 

    rand_sample[i, ]$maxWhite <- maxWhite 
    rand_sample[i, ]$minWhite <- minWhite 
    rand_sample[i, ]$maxBlack <- maxBlack 
    rand_sample[i, ]$minBlack <- minBlack 
    rand_sample[i, ]$sdWhite <- sdWhite 
    rand_sample[i, ]$sdBlack <- sdBlack 
    rand_sample[i, ]$avgTimeWhite <- avgW 
    rand_sample[i, ]$avgTimeBlack <- avgB 
} 

两个问题:你可以在这个for环表示

  1. 如何从$timestamp的每个列表中提取数据帧?

    rand_sample$times[[1]] 
    

    让我只是第一行。我希望能够像做

    rand_samples$dataFrameTimes <- rand_sample$times[[1]] 
    

    ,使得新列只是dataframes的列,而不是一个包含一个数据框的列表。

  2. 如何通过更快的机制模拟for循环?运行for循环需要每行大约1秒。我有一个包含数千行的数据集,所以这是站不住脚的。

+0

请提供可重现的实例中,例如通过使用rand_sample'的'的子集'dput' – Djork

+0

数据是专有的。有另一种方法吗? – Parseltongue

考虑转弯for环成lapply用于dataframes(等于rand_sample的行的列表,然后运行对列表do.call(rbind, ...)成一个单一的数据帧和最后cbindrand_sampletransform在端是去除不需要的现在时间

dfList <- lapply(rand_sample$times, function(current) { 

    mW <- abs(diff(current[[1]]$white)) 
    mB <- abs(diff(current[[1]]$black)) 

    data.frame(
    maxWhite = max(mW), 
    minWhite = min(mW), 
    maxBlack = max(mB), 
    minBlack = min(mB), 
    sdWhite = sd(mW), 
    sdBlack = sd(mB), 
    avgW = mean(mW), 
    avgB = mean(mB) 
) 
}) 

all_times <- do.call(rbind, dfList) 

finaldf <- transform(cbind(rand_sample, all_times), times=NULL) 

采样输入

rand_sample <- data.frame(
    ID = vapply(seq(50), function(i) sample(seq(15), 1, replace=TRUE), integer(1)), 
    GROUP = vapply(seq(50), function(i) sample(LETTERS, 1, replace=TRUE), character(1)) 
) 

rand_sample$times <- lapply(1:50, function(i) 
          list(data.frame(white=sample(1000:2000, 50), 
              black=sample(1000:2000, 50)))) 

输出

head(finaldf) 

# ID GROUP maxWhite minWhite maxBlack minBlack sdWhite sdBlack  avgW  avgB 
# 1 3  N  807  3  778  32 212.5353 177.5051 327.4082 297.3469 
# 2 12  Q  858  2  892  7 261.3543 222.4173 356.1837 366.7143 
# 3 6  R  749  13  910  8 208.5439 233.3391 324.6735 348.2041 
# 4 5  V  892  8  886  20 246.3769 261.3922 356.7347 329.5306 
# 5 4  O  842  5  886  2 200.1235 257.9464 350.2653 300.7347 
# 6 3  T  790  17  908  53 204.7842 235.0276 319.7959 385.1224 
+0

哇。这简直太不可思议了。你救了我这么头痛。为什么lapply比for循环快得多?我认为他们基本上是相同的运行时间。 – Parseltongue

+0

太棒了!乐意效劳。两者都是循环,但在这里我们运行批量操作而不是逐行操作。 – Parfait