data.table:查找每个组和列名称的重复数据。输出组和重复的列名

时间:2019-01-10 18:20:07

标签: r data.table

我希望使用data.table检测“冻结”的传感器数据。为此,我可以检查最近3天的数据,看看对于给定的列,该数据是否相同。我希望输出是被冻结的传感器的UID,然后是被冻结的传感器流的名称(即“温度”,“压力”等)。

示例:我有以下data.table:

library(data.table)
dt <- data.table(UID = c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3),
                 report_date = rep(seq.Date(as.Date("2019/1/1"), as.Date("2019/1/6"), 'days'), 3), 
                 temperature = c(101,103,105,101,105,104,105,103,101,102,102, 102,103,101,102,105,106,111), 
                 pressure = c(10.2,10.4,10.7,10.5,10.1,10.2,10.1,10.5,10.11,10.22,10.11,10.11,10.1,10.1,10.1,10.3,10.3,10.3), 
                 voltage = c(0.023,0.025,0.011,0.013,0.0254,0.028,0.028,0.077,0.026,0.0236,0.0258,0.0214,0.089,0.034,0.0387,0.0654,0.0246,0.02133))

dt
     UID report_date temperature pressure voltage
 1:   1  2019-01-01         101    10.20 0.02300
 2:   1  2019-01-02         103    10.40 0.02500
 3:   1  2019-01-03         105    10.70 0.01100
 4:   1  2019-01-04         101    10.50 0.01300
 5:   1  2019-01-05         105    10.10 0.02540
 6:   1  2019-01-06         104    10.20 0.02800
 7:   2  2019-01-01         105    10.10 0.02800
 8:   2  2019-01-02         103    10.50 0.07700
 9:   2  2019-01-03         101    10.11 0.02600
10:   2  2019-01-04         102    10.22 0.02360
11:   2  2019-01-05         102    10.11 0.02580
12:   2  2019-01-06         102    10.11 0.02140
13:   3  2019-01-01         103    10.10 0.08900
14:   3  2019-01-02         101    10.10 0.03400
15:   3  2019-01-03         102    10.10 0.03870
16:   3  2019-01-04         105    10.30 0.06540
17:   3  2019-01-05         106    10.30 0.02460
18:   3  2019-01-06         111    10.30 0.02133

输出应产生2行,即ID = 2和colID =“ temperature”的2行和ID = 3和colID =“ pressure”的2行。因为温度在ID = 2的最后3天中自身重复了3次ID等于3的压力。

    UID  colID
1.    2  temperature
2.    3  pressure

我可以想到使用基数R和循环执行此操作的方法,但是对于正确的data.table方法却迷茫了。

2 个答案:

答案 0 :(得分:4)

您可以使用

frozen = function(x) uniqueN(tail(x, 3)) == 1
dt[, .(colID = c(
  'temperature'[frozen(temperature)],
  'pressure'[frozen(pressure)])), 
  by=UID]
#    UID       colID
# 1:   2 temperature
# 2:   3    pressure

另一种版本是在对冻结的变量进行子设置之前融化数据。如果有很多测量变量,而不仅仅是如您示例中的温度和压力,这可能会更简洁。

cols = c('temperature', 'pressure')
dtm = melt(dt, id = 'UID', measure = cols)
dtm[, frozen(value), by = .(UID, variable)][(V1)]

关于正确测试值是否为“冻结”的注释

有多种方法可以测试同一向量的元素之间的相等性。查看答案here,了解一些选项。最好的方法取决于您的实际需求。像上面一样,使用UniqueN可以检查浮点数是否相同,是否确实冻结了这些值。根据您的特定用例以及仪器的工作方式,您可能更愿意根据不同的标准(例如,在绝对或相对机器公差范围内几乎相同)检查它们是否“相同”。对于某些细微差别,请务必阅读this answer上的评论。

如果您决定进行其他测试,只需在上面我使用UniqueN的地方替换它即可。

答案 1 :(得分:2)

对于较大的数据集和UID应该是快速的:

> dt[, .SD
     ][, melt(.SD, id.vars=c('UID', 'report_date'))
     ][order(UID, variable, -report_date)
     ][, rowid := rowid(UID, variable)
     ][rowid <= 3
     ][, .N, .(UID, variable, value)
     ][N == 3
     ][, setnames(.SD, 'variable', 'colID')
     ][, N := NULL
     ][, value := NULL
     ][]

   UID       colID
1:   2 temperature
2:   3    pressure
>