在列表中对所有数据框进行子集操作

4

我在使用R和stackoverflow上是新手。我试图处理一个数据框列表,并遇到了以下问题(希望这是一个好的复制示例)。假设我有一个包含4列的3个数据框的列表(我的真实代码包含10个数据框,每个数据框有20列):

df1 <- data.frame(k=20:0, h_1=rnorm(21), h_2=rnorm(21), h_3= rnorm(21))
df2 <- data.frame(k=20:0, h_1=rnorm(21), h_2=rnorm(21), h_3= rnorm(21))
df3 <- data.frame(k=20:0, h_1=rnorm(21), h_2=rnorm(21), h_3= rnorm(21))
df_list <- list(df1=df1,df2=df2,df3=df3)

每个数据框都有不同的子集条件:
例如:
#If I would subset them in a singular way outside of the list

df1_s <- df1[which(df1$k <=12 & df1$k >0), df1$h_1] #Taking only rows of k=12 to k=1 
and only the column h_1
df2_s <- df2[which(df2$k <=4 & df2$k >0), df2$h_3]
df3_s <- df3[which(df3$k <=12 & df2$k >0), df2$h_2]

我如何以最高效的方式对列表中的三个数据框进行子集操作? 我认为使用lapply并将子集编号放入向量中会是一个好的方法,但我不知道如何做或如何在列表中进行子集操作。
我希望你能帮助我。在发布之前,我尝试在其他帖子中寻找解决方案,但那些解决方案对我的代码无效。
4个回答

3

这是一个 mapply 方法(与其他答案的想法相同):

# function: w/ arguments dataframe and a vector = [column name, upper, lower]
rook <- function(df, par) {
  out <- df[par[1]][, 1]
  out[out <= par[2] & out > par[3]]
}

# list of parameters
par_list <- list(
  c('h_1', 12, 0),
  c('h_3', 4 , 0),
  c('h_2', 12, 0)
)

# call mapply
mapply(rook, df_list, par_list)

2
这里提供一种使用基础R的解决方案。正如@www所提到的,思路是使用一个应用程序型函数(mapplypurrr中的pmap)按顺序将多个参数应用于函数。此解决方案还利用了eval-parse结构来进行灵活的子集划分。例如,请参阅这里的讨论:http://r.789695.n4.nabble.com/using-a-condition-given-as-string-in-subset-function-how-td1676426.html
subset_fun <- function(data, criteria, columns) {
  subset(data, eval(parse(text = criteria)), columns)
}

criterion <- list("k <= 12 & k > 0", "k <= 4 & k > 0", "k <= 12 & k > 0")
cols <- list("h_1", "h_3", "h_2")

out <- mapply(subset_fun, df_list, criterion, cols)
str(out)
# List of 3
#  $ df1.h_1: num [1:12] -0.0589 1.0677 0.2122 1.4109 -0.6367 ...
#  $ df2.h_3: num [1:4] -0.826 -1.506 -1.551 0.862
#  $ df3.h_2: num [1:12] 0.8948 0.0305 0.9131 -0.0219 0.2252 ...

1
不错!我喜欢这个答案。 - johnson-shuffle
1
正如famous R user list所说:“如果答案是parse(),你通常应该重新考虑问题。——Thomas Lumley R-help(2005年2月)” - Parfait

1
我们可以使用包中的pmap函数。关键是定义一个函数,根据k和列名接受参数,然后使用这些参数组织一个列表,最后使用pmap函数。请保留html标签。
library(tidyverse)

# Define a function 
subset_fun <- function(dat, k1, k2, col){
  dat2 <- dat %>%
    filter(k <= k1, k > k2) %>%
    pull(col)
  return(dat2)
}

# Define lists for the function arguments
par <- list(dat = df_list,                   # List of data frames
            k1 = list(12, 4, 12),            # The first number 
            k2 = list(0, 0, 0),              # The second number
            col = list("h_1", "h_3", "h_2")) # The column name

# Apply the subset_fun
df_list2 <- pmap(par, subset_fun)
df_list2
# $df1
# [1] -0.6868529 -0.4456620  1.2240818  0.3598138  0.4007715  0.1106827 -0.5558411  1.7869131
# [9]  0.4978505 -1.9666172  0.7013559 -0.4727914
# 
# $df2
# [1] -0.9474746 -0.4905574 -0.2560922  1.8438620
# 
# $df3
# [1] -0.2803953  0.5629895 -0.3724388  0.9769734 -0.3745809  1.0527115 -1.0491770 -1.2601552
# [9]  3.2410399 -0.4168576  0.2982276  0.6365697

数据

set.seed(123)

df1 <- data.frame(k=20:0, h_1=rnorm(21), h_2=rnorm(21), h_3= rnorm(21))
df2 <- data.frame(k=20:0, h_1=rnorm(21), h_2=rnorm(21), h_3= rnorm(21))
df3 <- data.frame(k=20:0, h_1=rnorm(21), h_2=rnorm(21), h_3= rnorm(21))
df_list <- list(df1=df1,df2=df2,df3=df3)

我无法访问所有的包(和 purr)。有没有用 plyr 或基本 R 的方法可以做到这一点? - rook1996
@rook1996 然后像其他人建议的那样使用 mapply - www

1
考虑使用 Map,这是对 mapply 的封装,返回一个数据帧列表。由于你要对一列进行子集操作,为避免返回向量,需要使用 data.frame 进行转换,并使用 setNames 进行重命名。
在这里,选择使用 mapply 或者 Map,它们是 lapply 的姐妹函数,因为你想要对等长对象的列表逐元素迭代。Mapply 可以接收无限数量的参数,这里有四个参数,要求长度相等或长度的倍数:
low_limits <- c(0, 0, 0)
high_limits <- c(12, 4, 12)
h_cols <- c("h_1", "h_2", "h_3")

subset_fct <- function(df, lo, hi, col)  
               setNames(data.frame(df[which(df$k > lo & df$k <= hi), col]), col)

new_df_list <- Map(subset_fct, df_list, low_limits, high_limits, h_cols)

# EQUIVALENT CALL
new_df_list <- mapply(subset_fct, df_list, low_limits, 
                      high_limits, h_cols, SIMPLIFY = FALSE)

输出 (在顶部使用set.seed(456)以重现随机数)

new_df_list

# $df1
#           h_1
# 1   1.0073523
# 2   0.5732347
# 3  -0.9158105
# 4   1.3110974
# 5   0.9887263
# 6   1.6539287
# 7  -1.4408052
# 8   1.9473564
# 9   1.7369362
# 10  0.3874833
# 11  2.2800340
# 12  1.5378833

# $df2
#           h_2
# 1  0.11815133
# 2  0.86990262
# 3 -0.09193621
# 4  0.06889879

# $df3
#           h_3
# 1  -1.4122604
# 2  -0.9997605
# 3  -2.3107388
# 4   0.9386188
# 5  -1.3881885
# 6  -0.6116866
# 7   0.3184948
# 8  -0.2354058
# 9   1.0750520
# 10 -0.1007956
# 11  1.0701526
# 12  1.0358389

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接