【问题标题】:update data.table subset with function使用函数更新 data.table 子集
【发布时间】:2014-10-08 23:12:29
【问题描述】:

我有一个 data.table

dt2 <- data.table(urn=1:10,freq=0, freqband="")
dt2$freqband = NA
dt2$freq <- 1:7 #does give a warning message
##    urn freq freqband
## 1:   1    1       NA
## 2:   2    2       NA
## 3:   3    3       NA
## 4:   4    4       NA
## 5:   5    5       NA
## 6:   6    6       NA
## 7:   7    7       NA
## 8:   8    1       NA
## 9:   9    2       NA
##10:  10    3       NA

我还有一个函数想用来对我的频率列进行分组

fn_GetFrequency <- function(numgifts) {
    if (numgifts <5) return("<5")
    if (numgifts >=5) return("5+")
    return("ERROR")
}

我想根据这个函数设置 freqband 列。在某些情况下,它将是所有记录,在某些情况下,它将是一个子集。我目前的方法是(对于一个子集):

dt2[dt2$urn < 9, freqband := fn_GetFrequency(freq)]

使用这种方法我收到警告:

Warning message:
In if (numgifts < 5) return("<5") :
  the condition has length > 1 and only the first element will be used

然后它将所有记录的值设置为“

任何帮助将不胜感激。

编辑:如果你使用一个需要 2 个参数的函数,你会怎么做?

更新:在我尝试更新后包含 dt2 的输出

    urn freq freqband
 1:   1    1       <5
 2:   2    2       <5
 3:   3    3       <5
 4:   4    4       <5
 5:   5    5       <5
 6:   6    6       <5
 7:   7    7       <5
 8:   8    1       <5
 9:   9    2       NA
10:  10    3       NA

更新:我尝试了这段代码,它可以提供所需的输出,它允许我拥有一个我也可以在其他代码位置调用的函数。

dt2[dt2$urn < 9, freqband := sapply(freq, fn_GetFrequency)]

【问题讨论】:

  • 你定义的那个函数总是返回“ERROR”。您需要了解 if 和 'ifelse` 之间的区别。 R 不是 SAS。
  • @BondedDust 我没有得到“错误”,因为第一个值满足第一个条件,因此返回“

标签: r function data.table sapply


【解决方案1】:
> fn_GetFrequency <- function(numgifts) {
+     ifelse (numgifts <5, "<5", "5+")
+ }
> dt2[dt2$urn < 9, freqband := fn_GetFrequency(freq)]
> dt2
    urn freq freqband
 1:   1    1       <5
 2:   2    2       <5
 3:   3    3       <5
 4:   4    4       <5
 5:   5    5       5+
 6:   6    6       5+
 7:   7    7       5+
 8:   8    1       <5
 9:   9    2       NA
10:  10    3       NA

对于多个频段(我敢肯定之前有人问过),您应该使用findInterval 函数。而且我正在使用 data.table 方式而不是 dataframe 方式:

dt2[ urn==8, freq := -1 ] # and something to test the <0 condition

dt2[ urn <= 8, freqband := c("ERROR", "<5", "5+")[
                                  findInterval(freq,c(-Inf, 0, 5 ,Inf))] ]
dt2
    urn freq freqband
 1:   1    1       <5
 2:   2    2       <5
 3:   3    3       <5
 4:   4    4       <5
 5:   5    5       5+
 6:   6    6       5+
 7:   7    7       5+
 8:   8   -1    ERROR
 9:   9    2       NA
10:  10    3       NA

【讨论】:

  • 诚然,这个解决方案确实适用于上面的具体示例,而且我对我使用的功能有点狭隘。我应该使用 if(numgifts >0 & numgifts
  • 使用cutfindInterval
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 2014-01-08
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
相关资源
最近更新 更多