【问题标题】:Create a new colum based on a formula involving a lookup table根据涉及查找表的公式创建新列
【发布时间】:2017-01-07 16:14:21
【问题描述】:

我有一个这样的查找表:

0 1 2 3 4 5 6 7 8 9 h H k K m M b B   + - ? 
0 1 2 3 4 5 6 7 8 9 2 2 3 3 6 6 9 9 0 0 0 0  

使用此代码构建

symbols <- c("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "h", "H", "k", "K", "m", "M", "b", "B","", "+", "-", "?")
exp <- c(seq(0,9),2,2,3,3,6,6,9,9,0,0,0,0)
names(exp) <- symbols

执行exp[["k]] 确实返回3numeric

我有一个 data.table noaa 包含 2 列,一列带有值,一列带有指数代码,如“k”或 4。 这个 DT 来自这个文件:https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2

我想在该data.table中创建一个新列TOTALVALUE,例如值是(下面是伪代码中的公式)

noaa$TOTALVALUE = noaa$VALUE*10^exp[[noaa$EXPONENT]] in which noaa$EXPONENT value is matched using the exp matching table

我尝试了以下代码

noaa$test <- with(noaa, PROPDMG*10^exp[[PROPDMGEXP]])

我明白了

Error in exp[[PROPDMGEXP]] : 
       attempt to select more than one element in vectorIndex

如果我删除 [] 之一,它会进入无限循环并崩溃。

实现这一目标的最佳方法是什么?到目前为止,我想出的其他选择是将exp 构建为数据框并使用匹配,或者构建一个函数并在其上使用 lapply

【问题讨论】:

  • 请提供一个可重现的例子。 DTnoaa 是什么?顺便说一句,[[ 用于选择单个元素。对于多个条目,请使用 [as.vector(exp[c("1", "k")]) 而不是 exp[[c("1", "k")]]
  • 以下内容对您有用DT[, TOTALVALUE := VALUE*10^exp[EXPONENT]]
  • 我添加了 data.table 的来源,但我的问题是关于方法:如何在数据表上添加一个新列,该列将由涉及匹配表的计算填充?
  • 在这种情况下,第二条评论应该对您有所帮助。

标签: r data.table


【解决方案1】:

您的问题是您尝试使用[[ 进行矢量化选择,但[[ 总是 只选择一个元素。可以切换到[解决问题:

x = 1:3
names(x) = letters[1:3]
# x
# a b c 
# 1 2 3 

x[["a"]]
# [1] 1

x[[c("a", "c")]]
# Error in x[[c("a", "c")]] : 
#   attempt to select more than one element in vectorIndex

x["a"]
# a
# 1

# x[c("a", "c")]
# a c 
# 1 3 

正如评论者所指出的,最佳实践是使用:= 将列添加到data.table - 使用&lt;- 而不是:= 将错过data.table 的大部分效率。 Akrun 使用以下行的建议是完美的:

noaa[, TOTALVALUE := VALUE * 10 ^ exp[EXPONENT]]

【讨论】:

    【解决方案2】:

    除了

    noaa[, TOTALVALUE := VALUE * 10 ^ exp[EXPONENT]]
    

    效果很好但速度很慢,以下方法有效,而且速度更快。

    我没有构建一个命名向量,而是构建了一个包含 2 列的数据框:

    symbols <- c("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "h", "H", "k", "K", "m", "M", "b", "B","", "+", "-", "?")
    expValue <- c(seq(0,9),2,2,3,3,6,6,9,9,0,0,0,0)
    expTable <- data.frame(symbols, expValue)
    

    然后我使用 match 来查找值,最后创建了我需要的两列

    noaa[, PROPDGMGVALUE := PROPDMG * 10 ^ expTable[match(PROPDMGEXP, expTable$symbols),2]]
    noaa[, PROPDGMGVALUE := CROPDMG * 10 ^ expTable[match(CROPDMGEXP, expTable$symbols),2]]
    

    结果超过 900k 行,8 列 DT

    system.time(noaa[, pouet :=  PROPDMG*10^expValue[PROPDMGEXP]])
       user  system elapsed 
       223.11    0.03  223.28 
    
    system.time(noaa[, PROPDGMGVALUE := PROPDMG * 10 ^ expTable[match(PROPDMGEXP, expTable$symbols),2]])
        user  system elapsed 
        0.04    0.00    0.04 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      相关资源
      最近更新 更多