堆叠式循环可为大型数据集计算选择列的平均值

时间:2018-10-05 22:03:56

标签: r loops sequence

我有一个大型数据集,其中包含各种模型仿真的结果。我有84列,其中列1-2均为具有相同参数的模拟运行的结果,列3-4是第二组具有相同参数的2次运行的结果(与用于运行1-2的参数不同),第5-6列是具有相同参数(不同于先前运行所使用的参数)的第二组运行的第三组...等。

我需要R的代码,这将允许我对使用相同参数运行的模拟的所有行值求平均(例如,对1-2列的所有行值求平均值,然后对3-4列的所有值求平均值...)。

我正在使用以下代码首先生成一个数字序列,该数字序列根据每个模型的重复运行次数(run.num)以及运行总数(总计)来表示同一模型运行的列号运行)。这些变量可能会根据我设置模拟的方式而变化,因此我需要使我能够自动执行大多数步骤的代码。

# Define parameters of model assessment
run.num <- 2
total.runs <- 84
start.seq <- seq(1, total.runs, run.num)

# Creates empty space for the sequence values
sequences <- data.frame(matrix(total.runs/run.num, run.num))

# Creates the sequences 
for (i in start.seq){
 sequence <- seq(i, i + run.num - 1, 1)
 sequences[i, 1] <- sequence[1]
 sequences[i, 2] <- sequence[2] 
}

# Is there a way to automate how many of these "sequences[i, x] are generated 
based on run.num?

# Remove NA rows
sequences <- sequences[start.seq, ]

最后我得到一个表,其中每一行是一组模型运行,每列包含一个与列对应的“运行编号”值。现在,我想使用这些行号(代表我的数据集中的列号)来创建一个新的数据框(通过循环),该数据框仅包含列中所有行的所得平均值。

我不确定是否有更简单的方法来执行此操作,但是基本上,我需要使用代码来指定每个模型的重复运行次数,并获取每个重复运行的平均值。它需要尽可能的自动化,这样我就不必每次更改运行的仿真次数或每次仿真重复多少次时都更改太多代码。我想不出一种更简短的方式来解释这一点,我希望我对此有所理解。任何帮助深表感谢!

2 个答案:

答案 0 :(得分:1)

这是一种整洁的方法。不知道我是否能完全理解这个问题,但希望这能定向显示如何解决该问题。

library(tidyverse)
cols = 84
result_rows = 100
groupings = 2

fake <- data.frame(column = rep(paste0("Col_", 1:84), each = result_rows),
                   run    = rep(1:result_rows, cols),
                   result  = sample(c(1:10, NA_integer_),  cols * result_rows, replace = T)) %>%
  tidyr::spread(column, result)


output <- fake %>%
  # Pull into "long" format with a new column specifying the source column
  gather(column, result, -run) %>%
  # Extract the number from the column name
  mutate(col_num = str_remove(column, "Col_") %>% as.integer) %>%
  # Calculate what group the column belongs to
  mutate(group   = ceiling(col_num / groupings)) %>%
  # Calculate the mean per group
  group_by(group) %>%
  summarize(avg = mean(result, na.rm = T))

答案 1 :(得分:0)

我构建了一个包含6列的较小示例,但是您应该能够将您的应用程序的total.runs更改回84。我正在为重现性设置随机种子。我还在其中放置了一个NA值,只是为了向您展示它可以处理该值。可能有很多方法可以实现这一点,但这是一个。

run.num <- 2
total.runs <- 6
start.seq <- seq(1, total.runs, run.num)

set.seed(1)
df <- data.frame(
  c1 = sample(1:10, 100, replace = T),
  c2 = sample(1:10, 100, replace = T),
  c3 = sample(1:10, 100, replace = T),
  c4 = sample(1:10, 100, replace = T),
  c5 = sample(1:10, 100, replace = T),
  c6 = c(NA, sample(1:10, 99, replace = T))
)

我们首先使用lapply将数据框拆分为要对其行求和的数据框列表。如果令人困惑,请在线查看lapply的一些示例。如果run.num为3,这也将起作用(但由于4不会除以6,所以会在4或更大的值上中断)。

l <- lapply(start.seq, function(x) df[,x:(x + run.num - 1)])

然后我们再次lapply获取行总和,并将结果向量绑定到行总和的数据帧中。

ll <- lapply(l, function(df) rowSums(df, na.rm = T))

bind_cols(ll)
# A tibble: 100 x 3
      V1    V2    V3
   <dbl> <dbl> <dbl>
 1    10     6     3
 2    19    18    16
 3    20     9    14
 4    10    13     7
 5    15    10    15
 6    17     6     4
 7    11     8     3
 8     9     5    13
 9    10    12    10
10    20     5    14
# ... with 90 more rows

仅检查第一列的工作:

head(rowSums(df[,1:2], na.rm = T), 10)
 [1] 10 19 20 10 15 17 11  9 10 20