【问题标题】:How to apply function in each row in data.table如何在 data.table 的每一行中应用函数
【发布时间】:2015-10-19 09:04:37
【问题描述】:

假设我有以下内容

dt <- data.table(a=c(T,T,F,F), b= c(T,F,T,F))

返回,

       a     b
1:  TRUE  TRUE
2:  TRUE FALSE
3: FALSE  TRUE
4: FALSE FALSE

我曾尝试使用function(x) min(which(x)) 来确定@​​987654325@ 中每一行的第一个TRUE,但它不起作用。我期望的结果是

       a     b index
1:  TRUE  TRUE     1
2:  TRUE FALSE     1
3: FALSE  TRUE     2
4: FALSE FALSE  9999

,其中索引列表示第一个TRUE的位置,当该行仅包含FALSE时使用9999

仅供参考:在真实数据中,我有大约 50 列包含 TRUE 和 FALSE

你能给我一些建议吗?

【问题讨论】:

  • 试试dt[, index := ifelse(a, 1, ifelse(b, 2, 9999))] 我不确定 50 列的情况。你是说你有 TRUE、FALSE、50 列。在这种情况下,max.col(dt, 'first')*(!rowSums(dt)) 就是这样
  • @TimBiegeleisen 只是在评论我的空闲时间。
  • 如果您不介意 0 而不是 9999 作为所有 FALSE 的指示符,请尝试使用 max.col(dt,ties.method="first")*(rowSums(dt)!=0)(之后您也可以将其设置为 9999)。
  • @nicola 正打算提出相同的建议。虽然rowSums 在这里可能是一个开销。
  • @DavidArenburg 还有max.col 是。他们都强迫matrix。如果他的对象是矩阵,我提出的解决方案会更快。

标签: r data.table


【解决方案1】:

50列最好用max.col

dt$index <- max.col(dt, 'first') *(!!rowSums(dt))

或者正如@David Arenburg 提到的,更惯用的代码是

dt[, indx := max.col(.SD,ties.method="first")*(!!rowSums(.SD))]

如果我们需要9999

 (max.col(dt)*(!!rowSums(dt))) + (!rowSums(dt))*9999

【讨论】:

  • @nicola 在你提议之前,我确实更新了 cmets,请检查
  • 好的,我明白了。猜猜这个确切的问题已经被问过好几次了(这个确切的解决方案也是)。
  • dt[, indx := max.col(.SD,ties.method="first")*(!!rowSums(.SD))] 可能更惯用
  • 虽然这整件事一开始可能更适合矩阵,因为max.colrowSums 都转换为矩阵。
【解决方案2】:

有点晚了,但这是一种方式:

#initial data.table - added a row id
dt <- data.table(a=c(T,T,F,F), b= c(T,F,T,F))[, id := .I]

#if the row sums equal 0 then 9999 else pick the first max i.e. the first TRUE
dt[, index := if(rowSums(.SD)==0) 9999 else as.double(which.max(.SD)), by=id]

或者按照@David的评论,为了避免矩阵转换:

dt[, index := if(Reduce('+', .SD)==0) 9999 else as.double(which.max(.SD)), by=id]

输出:

> dt
       a     b id index
1:  TRUE  TRUE  1     1
2:  TRUE FALSE  2     1
3: FALSE  TRUE  3     2
4: FALSE FALSE  4  9999

【讨论】:

  • @DavidArenburg 是的,戴夫,你是对的。好多了。我会添加它。谢谢。
  • 我更担心循环遍历行而不是矩阵转换。
  • @Roland 是的,我同意这一点。我只是作为补充发布,因为标题更通用。它可能会帮助有不同问题的人。
【解决方案3】:

还有,

ans = rep_len(9999L, nrow(dt))
for(i in length(dt):1L) ans[dt[[i]]] = i
ans
#[1]    1    1    2 9999

【讨论】:

    猜你喜欢
    • 2023-03-06
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多