【问题标题】:apply a function in the j section of a data.table that only works on one value of vector at a time在 data.table 的 j 部分应用一个函数,该函数一次只对一个向量值起作用
【发布时间】:2017-12-08 11:40:51
【问题描述】:

一个可能的重复是here,但它对我没有帮助。我的情况可能不同。

考虑一个示例 data.table。

set.seed(21)
DT <- data.table(col1=sample(x=1:10,size = 5),col2=sample(x=10:20,size=5))
DT
   col1 col2
1:    8   20
2:    3   11
3:    6   19
4:    2   17
5:   10   15

并考虑一个函数check 我想应用于每一行:

check <- function(x,y) if ((y-x)>10) "A" else "B"

现在,如果我通过在DTj 部分调用函数check 来运行此分配,它会惨遭失败,

DT[,state:=check(col1,col2)]

并抛出此警告

Warning message:
In if ((y - x) > 10) "A" else "B" :
  the condition has length > 1 and only the first element will be used

显然,我猜 data.table 一次处理整个向量并且函数需要一个值,所以我认为最后一个值是向量中的当前值,所以我做了这个更改,这似乎是另一个愚蠢的举动:-)

DT[,state:=check(last(col1),last(col2))]

DT

   col1 col2 state
1:    8   20     B
2:    3   11     B
3:    6   19     B
4:    2   17     B
5:   10   15     B

我看到 check() 函数是针对最后一个值计算的,并且每次都会覆盖所有以前的值。我想要的是这个输出:

 DT

   col1 col2 state
1:    8   20     A
2:    3   11     A
3:    6   19     A
4:    2   17     A
5:   10   15     B

那么如何让函数调用在 data.table 中为每一行独立工作?

实际功能: 在我收到 akrun 的建议后,使用 ifelse,它适用于像 check() 这样的简单条件,但我这里有一个稍微复杂的功能。所以请将check替换为allowed_state

allowed_state <- function(old=NULL,new=NULL){
legalst<-data.table(from=c(1,1,9,9,7,8,7,10,10,11,11,10,11,8,7),to=c(11,7,10,7,8,7,9,9,7,1,7,1,7,9,10)) # all legal state transitions for a user
if(new %in% legalst[from==old,to]) "Legal" else "Illegal state change"

}

【问题讨论】:

  • 你需要ifelse 而不是if/elsecheck &lt;- function(x,y) ifelse((y-x)&gt;10, "A", "B")
  • 实际上,我的实际函数check 转换为ifelse 并不是那么简单。除非您可以建议一种转换方法。让我在问题中添加我的实际功能。
  • 会有帮助的
  • @akrun 你能查一下实际的功能(添加),现在让我们看看如何应用ifelse。我试过了,但是关于向量的大小有不同的警告。它对legalst[from==old,to] 部分不满意。

标签: r data.table


【解决方案1】:

如果我理解正确的话,OP 想要根据给定的表格legalst 合法状态变化来标记那些合法或非法的状态变化。

这可以通过加入更新来解决:

set.seed(21)
DT <- data.table(col1 = sample(x = c(1, 7:11), size = 5),
                 col2 = sample(x = c(1, 7:11), size = 5))
legalst <- data.table(from = c(1,1,9,9,7,8,7,10,10,11,11,10,11,8,7), 
                      to = c(11,7,10,7,8,7,9,9,7,1,7,1,7,9,10))

DT[legalst, on = .(col1 = from, col2 = to), state := "Legal"][
  is.na(state), state := "Illegal state change"][]
   col1 col2                state
1:   10   11 Illegal state change
2:    7    1 Illegal state change
3:    8   10 Illegal state change
4:    1    8 Illegal state change
5:   11    7                Legal

【讨论】:

  • 太棒了。这更好,因为它也不需要额外的功能。我会接受你的回答。
猜你喜欢
  • 1970-01-01
  • 2015-09-07
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
相关资源
最近更新 更多