【问题标题】:How do I subset multiple data frames using multiple variables如何使用多个变量对多个数据框进行子集化
【发布时间】:2018-07-30 14:44:40
【问题描述】:

我想根据一系列 31 个变量对五个数据框进行子集化。数据帧存储在一个列表中:

long_data_sets <- list(scale_g1, scale_g2, scale_g3, scale_g4, scale_g5)

五个数据帧中的每一个都包含一组相同的列,其中包括称为“speeder_225”到“speeder_375”的 31 个因子:

> str(scale_g1[53:83])
'data.frame':   5522 obs. of  31 variables:
$ speeder_225: Factor w/ 2 levels "Non-Speeder",..: 1 1 1 1 1 1 1 1 1 1 ...
$ speeder_230: Factor w/ 2 levels "Non-Speeder",..: 1 1 1 1 1 1 1 1 1 1 ...
$ speeder_235: Factor w/ 2 levels "Non-Speeder",..: 1 1 1 1 1 1 1 1 1 1 ...
$ speeder_240: Factor w/ 2 levels "Non-Speeder",..: 1 1 1 1 1 1 1 1 1 1 ...
$ speeder_245: Factor w/ 2 levels "Non-Speeder",..: 1 1 1 1 1 1 1 1 1 1 ... 
...

我想一次根据 31 个因子变量之一对数据帧进行子集化,这样我最终得到 5*31 个新数据帧。

我创建了子集函数,它只保留了我需要的两列(“方向”和“响应”):

create_speeder_data <- function(x, y){
  df <- subset(x, x[,y] == "Speeder",
              select = c("direction", "response"))
}

这允许我一次创建一个新的数据框:

create_speeder_data(scale_g1, "speeder_225")

我尝试使用 map2() 和 5 个数据框的列表以及 31 个因子名称的列表来应用该函数,但这显然不起作用。

> speeder_var <- names(scale_g1[53:83])
> map2(long_data_sets, speeder_var, create_speeder_data)
Error: `.x` (5) and `.y` (31) are different lengths

我能得到的最接近的方法是从我的函数中取出 y 参数,并将函数应用于 31 个因素之一的五个数据框列表。

#Create subsetting function for "speeder_225"
create_speeder_225_data <- function(x){
  df <- subset(x, x$speeder_225 == "Speeder",
               select = c("direction", "response"))
}

#Map function to list of data frames
z_speeder_225 <- map(long_data_sets, create_speeder_225_data)

#Change names of new data frames in list
names(long_data_sets) <- c("g1", "g2", "g3", "g4", "g5")
names(z_speeder_225) <- paste0(names_long_data_sets, "speeder_225")

#Get data frames from list
list2env(z_speeder_225, envir=.GlobalEnv)

我需要再重复 30 次才能得到我的 5*31 数据帧。必须有更简单的方法来做到这一点。

非常感谢任何帮助!

【问题讨论】:

  • 为什么需要 155 个单独的数据帧?对于很多分析,只使用分组来分离不同的因素更有意义。您可能需要先进行从宽到长的转换。
  • 顺便说一句,如果你展示一个具体的例子(不需要是你的真实数据)来说明问题,那么说明从宽到长等会更容易。例如,在 Gautam 的答案是,他创建了一个可以在其上运行代码的 data_list。除了那个很好的例子,这里还有一些其他的指导:stackoverflow.com/questions/5963269/…
  • 谢谢你们两位的cmets。不创建数据集而只使用分组并从那里开始确实有意义。连同@Gautam 的建议,这对我有用。以后发布问题时,我会确保遵循指南。

标签: r


【解决方案1】:

我同意@Mako212 - 你可能需要重新考虑你想要做什么。但是,这里有一些应该起作用的东西。

以下代码将对列表中的每个数据集进行子集化。在测试数据中有 5 个分类变量,每个变量有两个水平。由于 otuput 仅基于 1 个级别 (speeding),因此输出将是 5 x 5 = 25 个数据集。这被组织为列表列表 (5 x 5):

library(data.table)

# Creating some dummy data
k  <- 100
directions <- as.vector(sapply(c('North', 'West', 'South', 'East'), function (z) return(rep(z, k))))
speeding <- as.vector(sapply(c('speeding', 'not-speeding'), function (z) return(rep(z, k))))

# Test data - number_of_observations <= 4*k
createDataTable <- function(number_of_observations = 50){
  dt <- data.table(direction = sample(x = directions, size = number_of_observations, replace = T), 
                   speeder1 = sample(x = speeding, size = number_of_observations, replace = T), 
                   speeder2 = sample(x = speeding, size = number_of_observations, replace = T),
                   speeder3 = sample(x = speeding, size = number_of_observations, replace = T),
                   speeder4 = sample(x = speeding, size = number_of_observations, replace = T),
                   speeder5 = sample(x = speeding, size = number_of_observations, replace = T))
}

data_list <- lapply(X = floor(runif(n = 5, min = 50, max = 4*k)), 
                    FUN = function(z){createDataTable(z)})

# Subset dummy data based on one column at a time and return 
# the number of observations, direction, speeder2 and speeder3 from the subset 
cols <- sapply(1:5, function(z) paste('speeder',z,sep = ""))

ret <- lapply(cols, function(z){
  lapply(data_list, function(x){
    return(x[get(z) == 'speeding', .(nrows = .N, direction, speeder2, speeder3)])
  })
})

ret 的结构与我们预期的一致。每个项目都是 5 个 data.table 对象的列表,每个对象有 4 列。

> summary(ret)
     Length Class  Mode
[1,] 5      -none- list
[2,] 5      -none- list
[3,] 5      -none- list
[4,] 5      -none- list
[5,] 5      -none- list
> summary(ret[[1]])
     Length Class      Mode
[1,] 4      data.table list
[2,] 4      data.table list
[3,] 4      data.table list
[4,] 4      data.table list
[5,] 4      data.table list

快速测试看看代码是否运行良好并且没有错误地设置子集,这是一个简化的调用,只有子集标准的观察数/行数:

> unlist(lapply(cols, function(z){
+     lapply(data_list, function(x){
+         return(x[get(z) == 'speeding', .(nrows = .N)])
+     })
+ }))
nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows nrows 
  113    82    24   112   185    97    63    22   110   193   103    78    35   115   197   110    74 
nrows nrows nrows nrows nrows nrows nrows nrows 
   26   103   194   107    84    25    97   191 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 1970-01-01
    • 2011-06-23
    相关资源
    最近更新 更多