【问题标题】:Allow .SDcols to vary with grouping variable in data.table允许 .SDcols 随 data.table 中的分组变量而变化
【发布时间】:2016-02-19 08:49:24
【问题描述】:

是否允许 .SDcolsby 分组变量变化?我有以下情况,我想将.SDcols 更改为每年的不同列。 .SDcols 的值在一个 data.table 中,而我正在尝试使用这些值将函数应用于另一个表中的 .SD

很可能我错过了明显的方法并且做错了,但这就是我正在尝试的,

## Contains the .SDcols applicable to each year
dat1 <- data.table(
  year = 1:4,
  vals = lapply(1:4, function(i) letters[1:i])
)

## Make the sample data (with NAs)
set.seed(1775)
dat2 <- data.table( year = sample(1:4, 10, TRUE) )
dat2[, letters[1:4] := replicate(4, sample(c(NA, 1:5), 10, TRUE), simplify=FALSE)]

## Goal: Sum up the columns in the corresponding .SDcols for each year
## Attempt, doesn't work -- I think b/c .SDcols must be fixed?
dat2[, SUM := rowSums(.SD, na.rm=TRUE), by=year, 
  .SDcols=unlist(dat1[year == .BY[[1]], vals])]

## Desired result, by simply iterating through each possible year
for (i in 1:4) {
  dat2[year==i, SUM := rowSums(.SD, na.rm=TRUE), 
    .SDcols=unlist(dat1[year == i, vals])]
}

dat2[]
#     year  a  b c  d SUM
#  1:    1  3  1 5  1   3
#  2:    2  1  3 3  1   4
#  3:    1  5  4 3 NA   5
#  4:    4  1 NA 4  5  10
#  5:    2  2  2 2 NA   4
#  6:    2 NA  3 3 NA   3
#  7:    4  2  3 2 NA   7
#  8:    1  2 NA 5  4   2
#  9:    2  3  3 5  1   6
# 10:    3 NA  4 2 NA   6

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    在我看来,您只是在寻找一个简单的连接,同时通过dat1by = .EACHI))中的每个值更新值(通过引用)。无论哪种方式,rowSums 都是这个解决方案的瓶颈和你的尝试(因为矩阵转换)。如果我是你,我会将所有NAs 转换为零并运行Reduce(`+`,...)(不确定是否要更改原始数据中的值)

    dat2[dat1, 
          SUM := rowSums(.SD[, unlist(i.vals), with = FALSE], na.rm = TRUE), 
          on = "year", 
         by = .EACHI]
    dat2
    #     year  a  b c  d SUM
    #  1:    1  3  1 5  1   3
    #  2:    2  1  3 3  1   4
    #  3:    1  5  4 3 NA   5
    #  4:    4  1 NA 4  5  10
    #  5:    2  2  2 2 NA   4
    #  6:    2 NA  3 3 NA   3
    #  7:    4  2  3 2 NA   7
    #  8:    1  2 NA 5  4   2
    #  9:    2  3  3 5  1   6
    # 10:    3 NA  4 2 NA   6
    

    如果我是你,如前所述,我会将NAs 转换为零并改用Reduce

    for(j in 2:ncol(dat2)) set(dat2, i = which(is.na(dat2[[j]])), j = j, value = 0L)
    dat2[dat1,
           SUM := Reduce(`+`, .SD[, unlist(i.vals), with = FALSE]), 
           on = "year", 
        by = .EACHI]
    dat2
    #     year a b c d SUM
    #  1:    1 3 1 5 1   3
    #  2:    2 1 3 3 1   4
    #  3:    1 5 4 3 0   5
    #  4:    4 1 0 4 5  10
    #  5:    2 2 2 2 0   4
    #  6:    2 0 3 3 0   3
    #  7:    4 2 3 2 0   7
    #  8:    1 2 0 5 4   2
    #  9:    2 3 3 5 1   6
    # 10:    3 0 4 2 0   6
    

    【讨论】:

    • unlist(i.vals) 让我很困惑。我确定这是.EACHI 问题。 +1
    • @AnandaMahto 它也可以在没有i. 的情况下工作,我只是始终使用它来确保安全(以防其他数据集中也有类似的列),或者您只是指by = .EACHI 部分?
    猜你喜欢
    • 2021-12-05
    • 2020-08-19
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多