【问题标题】:Removing an out of sequence number from a column in data.table in R [closed]从R中的data.table中的列中删除序列号[关闭]
【发布时间】:2017-10-21 00:39:03
【问题描述】:

我有一个数据表 dt,包含三列 nm、seqn 和 obj

> nm <- letters[1:22]
> seqn <- c(32,36, 86,45 , 47, 48, 49,
+            52, 54, 59, 
+            66, 9, 69, 74, 81, 88, 90, 91, 93, 94, 95, 97)
> obj <- rep(c('c1', 'c2', 'c3'), c(7, 3, 12))
> dt <- data.table(nm, seqn, obj)
> dt
    nm seqn obj
 1:  a   32  c1
 2:  b   36  c1
 3:  c   86  c1
 4:  d   45  c1
 5:  e   47  c1
 6:  f   48  c1
 7:  g   49  c1
 8:  h   52  c2
 9:  i   54  c2
10:  j   59  c2
11:  k   66  c3
12:  l    9  c3
13:  m   69  c3
14:  n   74  c3
15:  o   81  c3
16:  p   88  c3
17:  q   90  c3
18:  r   91  c3
19:  s   93  c3
20:  t   94  c3
21:  u   95  c3
22:  v   97  c3

我想为每个“obj”组获得一个单调的“seqn”序列。我想在 obj "c1" 的情况下删除像 86(record 3) 这样的序列号(* 这里 86 是一个大数字,而通常是一系列小的单调 seqn 数字),在 obj "c3" 的情况下,我想要删除 seqn 9。(记录 12)(* 这里 9 是大数字单调 seqn 中的一个小数)。

如何使用 data.table/dataframe 做到这一点。

【问题讨论】:

  • 我的逻辑是在较大的数字前后删除较小的数字,并在较大的数字前后删除较小的数字。那怎么办?
  • 另外两个问题看起来几乎相同(数据除外):stackoverflow.com/questions/44030594/…stackoverflow.com/questions/44027088/…
  • @Uwe:我是这么想的,但他们实际上有一个“最大重启”,这使它更容易且不可转移。 @Ravi:你可以这样做:dt[!((seqn &lt; shift(seqn, fill=0, type = "lag") | seqn &gt; shift(seqn, fill=999, type = "lead")) &amp; shift(seqn, fill=999, type = "lead") &gt; shift(seqn, fill=999, type = "lag")), .SD, by = obj][]
  • 好像你不使用数据表。确保清除您的环境,在发布数据时重新加载数据,检查它是否属于数据表类型,然后在我的评论中运行代码,...对我来说可行。
  • @BigDataScientist OP 刚刚在this comment 中披露了 2 个附加要求,包括在达到最大值后重新启动和消除最多三个连续的失序值。这使得他的问题完全重复了另外两个链接的 Q,IMO。

标签: r dataframe data.table


【解决方案1】:

这是另一个data.table 解决方案,它与this comment 中建议的解决方案不同。

OP 已请求为每个 obj 组获取 seqn 的单调序列。此外,OP 有detailed,他需要 在其前面和后面跟着较小的数字时删除一个较大的数字,并在它前面和后面跟着较大的数字时删除一个较小的数字。虽然不是明确指出,从提供的数据可以得出结论,OP 指的是单调递增序列。

library(data.table)
DT[-DT[, .I[which(xor(
  shift(seqn) < shift(seqn, type = "lead"),
  between(seqn, shift(seqn), shift(seqn, type = "lead"))
))], by = obj]$V1]
#    nm seqn obj
# 1:  a   32  c1
# 2:  b   36  c1
# 3:  d   45  c1
# 4:  e   47  c1
# 5:  f   48  c1
# 6:  g   49  c1
# 7:  h   52  c2
# 8:  i   54  c2
# 9:  j   59  c2
#10:  k   66  c3
#11:  m   69  c3
#12:  n   74  c3
#13:  o   81  c3
#14:  p   88  c3
#15:  q   90  c3
#16:  r   91  c3
#17:  s   93  c3
#18:  t   94  c3
#19:  u   95  c3
#20:  v   97  c3

数据

library(data.table)
nm <- letters[1:22]
seqn <- c(32,36, 86,45 , 47, 48, 49, 52, 54, 59, 
          66, 9, 69, 74, 81, 88, 90, 91, 93, 94, 95, 97)
obj <- rep(c('c1', 'c2', 'c3'), c(7, 3, 12))
DT <- data.table(nm, seqn, obj)

在每个序列的开头和结尾违反单调性

可以增强上述方法以覆盖在每个序列的开始或结束处违反单调性的边缘情况,即对于每个obj 组。

例如:

seqn <- c(32,36, 86, 45, 47, -48, 49, 52, 54, 59, 
          66, 9, 13, 74, 81, 88, 90, 91, 93, 94, 95, 11)
(DT <- data.table(nm, seqn, obj))
#    nm seqn obj
# 1:  a   32  c1
# 2:  b   36  c1
# 3:  c   86  c1
# 4:  d   45  c1
# 5:  e   47  c1
# 6:  f   48  c1
# 7:  g   49  c1
# 8:  h   52  c2
# 9:  i   54  c2
#10:  j   59  c2
#11:  k   66  c3
#12:  l    9  c3
#13:  m   13  c3
#14:  n   74  c3
#15:  o   81  c3
#16:  p   88  c3
#17:  q   90  c3
#18:  r   91  c3
#19:  s   93  c3
#20:  t   94  c3
#21:  u   95  c3
#22:  v   11  c3
#    nm seqn obj

请注意,DT 在第 13 行和第 22 行中已更改。现在,objc3 的第一个和最后一个元素已成为“异常值”。第一个元素 66 大于接下来的两个元素 9 和 13,最后一个元素 11 小于前面的元素 95。因此,单调递增序列以 9 开​​始,以 95 结束,元素 66 和 11 必须被删除。

这可以通过简单地用前导 -Inf 和尾随 +Inf 填充每个序列来实现。除了必须将结果移回以选择正确的行号之外,不需要对代码进行其他更改:

DT[-DT[, {seqn <- c(-Inf, seqn, +Inf); .I[which(shift(xor(
  shift(seqn) < shift(seqn, type = "lead"),
  between(seqn, shift(seqn), shift(seqn, type = "lead"))
), type = "lead"))]}, by = obj]$V1]
#    nm seqn obj
# 1:  a   32  c1
# 2:  b   36  c1
# 3:  d   45  c1
# 4:  e   47  c1
# 5:  f   48  c1
# 6:  g   49  c1
# 7:  h   52  c2
# 8:  i   54  c2
# 9:  j   59  c2
#10:  l    9  c3
#11:  m   13  c3
#12:  n   74  c3
#13:  o   81  c3
#14:  p   88  c3
#15:  q   90  c3
#16:  r   91  c3
#17:  s   93  c3
#18:  t   94  c3
#19:  u   95  c3

【讨论】:

  • 我不明白这一点,当 obj = c2 时它也会删除所有观察结果
  • @RaviMishra 放错了减号。代码现已修复。
  • 这段代码删除seqn 9失败,对于obj c3,如果69被其他seqn替换,比如13,请在下一条评论中参考以下数据
  • seqn
  • 这是一个令人讨厌的惊喜!你现在告诉我——在我花了几个小时为寻找答案之后——你在最初的问题中没有描述额外的要求?
猜你喜欢
  • 2012-05-21
  • 2021-03-06
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多