【问题标题】:Subsetting data table based on patterns in data根据数据中的模式对数据表进行子集化
【发布时间】:2016-09-01 09:06:54
【问题描述】:

我有一个这样的数据表:

z
     a   b negflag
 1:  1  41       0
 2:  2  61       0
 3:  3 623       0
 4:  4 -12       1
 5:  5  10       0
 6:  6  15       0
 7:  7  16       0
 8:  8  -9       1
 9:  9  31       0
10: 10  10       0

我想做的是在“negflag”旁边添加一列,它告诉我b列中是否有一个正值,之前2行。

像这样:

     a   b negflag posflag
 1:  1  41       0       0
 2:  2  61       0       1
 3:  3 623       0       1
 4:  4 -12       1       0
 5:  5  10       0       0
 6:  6  15       0       1
 7:  7  16       0       1
 8:  8  -9       1       0
 9:  9  31       0       0
10: 10  10       0       0

因此,如果在负数发生之前存在正值 1 和 2 行(含),我希望另一列给出 1。

问候

【问题讨论】:

  • 最后一个值不应该是1吗?
  • 我只关心它是否出现在 b 列中的负数之前 1 或 2 行。
  • 那么子设置到底发生在哪里?同样在您的示例中,您首先声明:“如果 b 列中存在正值,则之前为 2 行。”,然后您声明“如果在负值之前有 1 和 2 行(包括)正值,则给出 1发生了。”在上面的评论中你说“之前有 1 或 2 行”......是哪一个?如果是 1 OR 2 不都是 1 吗?

标签: r data.table


【解决方案1】:

此答案的第一次迭代没有考虑提供的数据集中不存在的几种情况(尽管它确实在提供的数据上给出了预期的输出)。使用新数据集znew,您将需要另一个过程来获得正确的输出,从而满足问题中的指定条件:

znew[, pf := as.integer(b < 0 & shift(b, fill = 0) > 0 & shift(b, n = 2L, fill = 0) > 0)
     ][, posflag := as.integer(shift(pf, type = 'lead', fill = 0)==1 | shift(pf, n = 2L, type = 'lead', fill = 0)==1)
       ][, pf := NULL]

或者(根据@Frank的建议):

idx <- znew[, .I[b < 0 & do.call(pmin, shift(b, 1:2, fill=0L)) > 0]]
znew[, posflag := 0L][c(idx-1L, idx-2L), posflag := 1L]

两者都给出:

> znew
     a   b negflag posflag
 1:  1 -41       1       0
 2:  2  61       0       1
 3:  3 623       0       1
 4:  4 -12       1       0
 5:  5  10       0       0
 6:  6 -15       1       0
 7:  7  16       0       0
 8:  8  -9       1       0
 9:  9  31       0       0
10: 10  10       0       0

这两种方法首先确定是否满足条件(b 列中的负值的两个正值先前值)并创建posflag 变量。


使用过的数据

znew <- fread('a  b  negflag
 1   -41     1
 2    61     0
 3   623     0
 4   -12     1
 5    10     0
 6   -15     1
 7    16     0
 8    -9     1
 9    31     0
10    10     0')

旧答案:您可以使用data.table 中的shift 函数,如下所示:

z[, posflag := as.integer(b > 0 & shift(b) > 0 & (shift(b, type = 'lead', 
           fill = 0) < 0 | shift(b, n = 2L, type = 'lead', fill = 0) < 0))]

会给你:

> z
     a   b negflag posflag
 1:  1  41       0       0
 2:  2  61       0       1
 3:  3 623       0       1
 4:  4 -12       1       0
 5:  5  10       0       0
 6:  6  15       0       1
 7:  7  16       0       1
 8:  8  -9       1       0
 9:  9  31       0       0
10: 10  10       0       0

【讨论】:

  • 最终可以优化为在实现data.table#1708 时在{ 内调用单个shift
  • @jangorecki 那太好了!
猜你喜欢
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 2013-04-22
相关资源
最近更新 更多