【问题标题】:Returning a list of data.tables from sapply [closed]从 sapply 返回 data.tables 列表 [关闭]
【发布时间】:2017-06-02 21:37:33
【问题描述】:

我有一个有趣的问题。我有一些未知数量的巨大表,但至少有 2 个。它们具有相同的架构,我想从每个表中提取子集并创建一个专门的交叉连接,以便我可以组合各个部分。

所以从 2 个 data.table 对象的简单示例开始:

DT1 <- data.table(A = rep(1:2, each = 2), B = rep(1:2, 2), C = sample(4))
DT2 <- data.table(A = rep(1:2, 2), B = sample(4), C = rep(1:2, each = 2))

> DT1
A B C
1 1 2
1 2 3
2 1 1
2 2 4

> DT2
A B C
1 2 1
2 1 1
1 3 2
2 4 2

因为我最终不知道我将要对多少表进行子集化,所以我创建了一个列表并将其传递给一个函数以使用 sapply 进行子集化:

tables = list(DT1, DT2)
foo <- function(dt, value) {
  result <- dt[A == value,]
  return(result)
}

combined <- sapply(tables, foo, value = 1)

然而,组合的结果是没有模式的向量的混乱。我想要返回的是 data.tables 列表。 foo 函数返回一个 data.table,但结果在 sapply 中被打乱了。如何修改代码以执行类似的操作?

combined <- list(DT1[A == 1,], DT2[A == 1])

生成 data.tables 列表

> combined
[[1]]
   A B C
1: 1 1 2
2: 1 2 3

[[2]]
   A B C
1: 1 2 1
2: 1 3 2

TIA 一如既往。

【问题讨论】:

  • sapply 试图简化结果。如果你想要一个列表作为结果,你需要使用lapply
  • 把这个归档到doh下!

标签: r data.table sapply


【解决方案1】:

下面是另一种使用dplyrlapply 的方法。扩展这项工作可以使其更具活力。

library(dplyr)
library(data.table)
set.seed(42)

DT1 <- data.table(A = rep(1:2, each = 2), B = rep(1:2, 2), C = sample(4))
DT2 <- data.table(A = rep(1:2, 2), B = sample(4), C = rep(1:2, each = 2))
DT3 <- data.table(A = rep(1:2, each = 2), B = sample(4), C = rep(1:2, times = 2))
DT4 <- data.table(A = rep(1:2, 2), B = sample(4), C = rep(1:2, each = 2))

# View the data.tables
list(DT1, DT2, DT3, DT4)
# [[1]]
#    A B C
# 1: 1 1 4
# 2: 1 2 3
# 3: 2 1 1
# 4: 2 2 2
# 
# [[2]]
#    A B C
# 1: 1 3 1
# 2: 2 2 1
# 3: 1 4 2
# 4: 2 1 2
# 
# [[3]]
#    A B C
# 1: 1 3 1
# 2: 1 4 2
# 3: 2 1 1
# 4: 2 2 2
# 
# [[4]]
#    A B C
# 1: 1 4 1
# 2: 2 1 1
# 3: 1 3 2
# 4: 2 2 2
# 

# Get a List of data.tables For A == 1
lapply(list(DT1, DT2, DT3, DT4),
       function(.data, ...) { as.data.table(dplyr::filter_(.data, ...)) },
       ~ A == 1)
# [[1]]
#    A B C
# 1: 1 1 4
# 2: 1 2 3
# 
# [[2]]
#    A B C
# 1: 1 3 1
# 2: 1 4 2
# 
# [[3]]
#    A B C
# 1: 1 3 1
# 2: 1 4 2
# 
# [[4]]
#    A B C
# 1: 1 4 1
# 2: 1 3 2
# 

# Get a List of data.tables For A == 2
lapply(list(DT1, DT2, DT3, DT4),
       function(.data, ...) { as.data.table(dplyr::filter_(.data, ...)) },
       ~ A == 2)
# [[1]]
#    A B C
# 1: 2 1 1
# 2: 2 2 2
# 
# [[2]]
#    A B C
# 1: 2 2 1
# 2: 2 1 2
# 
# [[3]]
#    A B C
# 1: 2 1 1
# 2: 2 2 2
# 
# [[4]]
#    A B C
# 1: 2 1 1
# 2: 2 2 2
# 

扩展此方法以允许更复杂的过滤条件很容易。您需要做的就是在lapply 调用中添加条件。

# Get a list of data.tables for A == 2 and B == 1
lapply(list(DT1, DT2, DT3, DT4),
       function(.data, ...) { as.data.table(dplyr::filter_(.data, ...)) },
       ~ A == 2, ~ B == 1)
# [[1]]
#    A B C
# 1: 2 1 1
# 
# [[2]]
#    A B C
# 1: 2 1 2
# 
# [[3]]
#    A B C
# 1: 2 1 1
# 
# [[4]]
#    A B C
# 1: 2 1 1
# 

【讨论】:

    【解决方案2】:
    foo <- function(dt, value) {
      result <- dt[A == value,]
      return(result)
    }
    
    combined <- lapply(tables, foo, value = 1)
    

    【讨论】:

    • 不,使用split。见?split
    猜你喜欢
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2017-11-01
    • 2016-07-20
    • 2015-07-04
    • 2017-02-27
    • 1970-01-01
    相关资源
    最近更新 更多