【问题标题】:Find rows with a given difference between values in a column查找列中的值之间具有给定差异的行
【发布时间】:2012-05-23 18:12:52
【问题描述】:

对于 R 中的 data.table(或 data.frame),我希望找到所有包含列“值”中的值的行,这些行与具有相同键的行中的另一个值的给定距离“距离” .因此,鉴于以下情况:

distance <- 22
   key value
   A     1
   B     1
   C     1
   D     1
   A     4
   B     4
   A    23
   B    23
   B    26
   B    26
   C    30

我想用相同键的行数和一个 +22 的值来注释原始表:

  key value count
  A     1     1
  B     1     1
  C     1     0
  D     1     0
  A     4     0
  B     4     2
  A    23     0
  B    23     0
  B    26     0
  B    26     0
  C    30     0

我真的不知道从哪里开始使用这种在 R 中操作数据的自引用方法。我最初的尝试涉及创建第二个表并尝试与之匹配,但这似乎是一种奇怪且糟糕的方法。

注意:我正在使用 data.table 包,但我很乐意在这种情况下使用 data.frame 工作,如果这样可以让事情变得更容易。

可重现性:

require(data.table)
source <- data.table(data.frame(key=c("A","B","C","D","A","B","A","B","B","B", "C"),value=c(1,1,1,1,4,4,23,23,26,26,30)))
result <- data.table(data.frame(key=c("A","B","C","D","A","B","A","B","B","B","C"),value=c(1,1,1,1,4,4,23,23,26,26,30),count=c(1,1,0,0,0,2,0,0,0,0,0)))

【问题讨论】:

    标签: r dataframe data.table


    【解决方案1】:

    这是一个基于data.table 的解决方案。我有兴趣了解可以对其进行哪些改进(如果有的话)。

    # Your code
    library(data.table)
    source <- 
    data.table(data.frame(key = c("A","B","C","D","A","B","A","B","B","B", "C"),
                          value = c(1,1,1,1,4,4,23,23,26,26,30)))
    

    那个奇怪的data.table(data.frame(... 是因为data.table() 也有一个叫key 的参数。这是使用名为"key" 的列创建data.table 的一种方法。大写以避免参数名称冲突说明了更标准的语法:

    source <- data.table(Key = c("A","B","C","D","A","B","A","B","B","B","C"),
                         Value = c(1,1,1,1,4,4,23,23,26,26,30))
    

    接下来为了避免以后需要as.integer(),我们现在将Value 列的类型从numeric 更改为integer。请记住,R 中的1numeric,它是1L,即integer。将integer 数据存储为integer 通常比将integer 存储为numeric 效率更高。下一行比在上面输入大量Ls 更容易。

    source[,Value:=as.integer(Value)]   # change type from `numeric` to `integer`
    

    现在继续

    distance <- 22L
    setkey(source, Key, Value)
    
    # Heart of the solution (following a few explanatory comments):
    #  "J()"   : shorthand for 'data.table()'
    #  ".N"    : returns the number of rows that matched a line (see ?data.table)
    #  "[[3]]" : as with simple data.frames, extracts the vector in column 3
    
    source[,count:=source[J(Key,Value+distance),.N][[3]]]
    source
          key value count
     [1,]   A     1     1
     [2,]   A     4     0
     [3,]   A    23     0
     [4,]   B     1     1
     [5,]   B     4     2
     [6,]   B    23     0
     [7,]   B    26     0
     [8,]   B    26     0
     [9,]   C     1     0
    [10,]   C    30     0
    [11,]   D     1     0
    

    请注意,:= 直接通过引用更改了source,就是这样。但是setkey()也改变了原始数据的顺序。如果需要保留原订单,则:

    source <- data.table(Key = c("A","B","C","D","A","B","A","B","B","B","C"),
                         Value = c(1,1,1,1,4,4,23,23,26,26,30))
    source[,Value:=as.integer(Value)]   
    source[,count:=setkey(copy(source))[source[,list(Key,Value+distance)],.N][[3]]]
    
          Key Value count
     [1,]   A     1     1
     [2,]   B     1     1
     [3,]   C     1     0
     [4,]   D     1     0
     [5,]   A     4     0
     [6,]   B     4     2
     [7,]   A    23     0
     [8,]   B    23     0
     [9,]   B    26     0
    [10,]   B    26     0
    [11,]   C    30     0
    

    【讨论】:

    • 谢谢,你能解释一下分配 result$count 的那行吗? .N 和 [[3]] 是什么意思?
    • 当然。我只是在代码中添加了一些 cmets,它们开始解压缩 data.table 调用的紧凑语法。
    • @Ina 哎呀,您真的要保留原始表的顺序吗?我错过了那一点。
    • 不,不需要保留订单。实际上它无论如何都是一个键控数据表,所以我写出的表具有误导性,并且在 R 中打印时会按键排序。
    • @MatthewDowle -- 出色的编辑。我对DT$count &lt;- 构造不满意,现在看看如何始终避免它。 (开始视觉解析嵌套的[]s 确实需要一段时间,这是有效data.table 使用的重要组成部分。就我而言,真正开始使用它需要大约5个月,但我想我'我就在那儿。)像往常一样感谢您的帮助。
    【解决方案2】:

    您可以使用mapply 循环遍历键和值的所有组合:

    data.table(t(mapply(function(key,val) 
          c(key=key,value=val,count=length(source$value[source$key==key & source$value>(val+distance)]) )
       , as.character(source$key),source$value)))
    

    【讨论】:

    • 这似乎产生了错误的结果,使用这个公式,我在第二行得到了 2 的计数,在第三行得到了 1 的计数。我想我明白它在做什么,但我看不到一个明显的错字会使这成为一个简单的错误。此外,理想情况下,答案的复杂度不会是 n^2,但这可能是不可能的。
    猜你喜欢
    • 2015-06-27
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多