【问题标题】:R DataTable Join and constrain rowsR DataTable 连接和约束行
【发布时间】:2013-09-23 04:13:59
【问题描述】:

我想在数据表中总结一组观察结果,并可以在语法方面使用一些帮助。

我认为这与连接一样简单,但我试图确定在特定观察日看到的特定值,即使它在当天跨越多个测量值或传感器。

  • 观察结果按日期汇总
  • 观察日期有不同的测量计数(每个日期的行数)
  • “测量”列表示当天在任何传感器中都观察到了特定值。

我创建了 2 个样本数据集,希望能阐明目标。我还创建了一个 Excel 电子表格的图像,希望显示数据之间的关系。

library(data.table)
raw <- data.table(
  Date = as.Date(c("2013-5-4","2013-5-4","2013-5-4", "2013-5-9","2013-5-9", "2013-5-16","2013-5-16","2013-5-16", "2013-5-30")),
  S1 = c(4, 2, 3, 1, 1, 8, 7, 3, 3),
  S2 = c(2, 5, 2, 4, 4, 9, 1, 6, 4),
  S3 = c(6, 2, 2, 7, 3, 2, 7, 2, 1)
)

summarized <- data.table(
  Date = as.Date(c("2013-5-4", "2013-5-9", "2013-5-16", "2013-5-30")),
  M1 = c(FALSE,TRUE,TRUE,TRUE),
  M2 = c(TRUE,FALSE,TRUE,FALSE),
  M3 = c(TRUE,TRUE,TRUE,TRUE),
  M4 = c(TRUE,FALSE,FALSE,TRUE),
  M5 = c(TRUE,FALSE,FALSE,FALSE),
  M6 = c(TRUE,FALSE,TRUE,FALSE),
  M7 = c(FALSE,TRUE,TRUE,FALSE),
  M8 = c(FALSE,FALSE,TRUE,FALSE),
  M9 = c(FALSE,FALSE,TRUE,FALSE),
  M10 = c(FALSE,FALSE,TRUE,FALSE)
)

电子表格

Raw 是测量输入。可以在同一观察日期进行多次测量(即多行)。

总结是我希望得到的。行被汇总,“m”测量列仅表示在任何 V 列中当天观察到的值(在 M 之后,即 M1、M2 之后)。例如,数字 2 在 5/16 的第一次和最后一次观察中出现,但在 5/16 的 9 个值中都没有出现数字 5。

我认为我需要使用连接,但如何计算 M 列让我无法理解。

非常感谢任何帮助。

问题:这种类型的运算在数据科学或数学中有名称吗?

更新: 我正在尝试以下方法

setkey(raw,Date)
s <- data.table( Date=unique(raw$Date)) # get a datatable of the unique dates
setkey(s,Date)
s[raw, M1:=(length(na.omit(match(c(raw$V1,raw$v2,raw$v3),1)))>=1)]

请注意,这些值不是 5-4 的预期值(应该为 FALSE)。我认为这是因为原始行在我的匹配语句中不受限制。

         Date   M1
1: 2013-05-04 TRUE
2: 2013-05-09 TRUE
3: 2013-05-16 TRUE
4: 2013-05-30 TRUE

我的猜测是我需要使用不同的方法来对联接中的原始行进行子集化。

【问题讨论】:

标签: r data.table reshape


【解决方案1】:

这似乎有效:

raw[,lapply(1:10,`%in%`,unique(unlist(.SD))),by=Date]

结果是

         Date    V1    V2   V3    V4    V5    V6    V7    V8    V9   V10
1: 2013-05-04 FALSE  TRUE TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE
2: 2013-05-09  TRUE FALSE TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE
3: 2013-05-16  TRUE  TRUE TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE
4: 2013-05-30  TRUE FALSE TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

如果您想要使用“M”而不是“V”的列,请使用c(M=1:10) 代替1:10

【讨论】:

    【解决方案2】:

    这是一个重塑问题。

    首先,由于数据来自哪个传感器并不重要,让我们将您的三列聚合为一列。

    temp <- raw[,Reduce(union,list(S1,S2,S3)),by=Date]
    

    现在我们要从“长”格式重塑为“宽”格式。

    借用this answer的一个数据表解决方案:

    setkey(temp,Date,V1)
    temp[CJ(unique(Date),unique(V1)), list(.N)][,
      setNames(as.list(as.logical(N)), paste0("M",unique(V1))), by = Date]
             # Date    M1    M2   M3    M4    M5    M6    M7    M8    M9
    # 1: 2013-05-04 FALSE  TRUE TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE
    # 2: 2013-05-09  TRUE FALSE TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE
    # 3: 2013-05-16  TRUE  TRUE TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
    # 4: 2013-05-30  TRUE FALSE TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
    

    基础reshape 是这样工作的:

    as.data.table(reshape(temp, timevar = "V1", v.names = "V1", idvar = "Date", direction = "wide"))
             # Date V1.4 V1.2 V1.3 V1.5 V1.6 V1.1 V1.7 V1.8 V1.9
    # 1: 2013-05-04    4    2    3    5    6   NA   NA   NA   NA
    # 2: 2013-05-09    4   NA    3   NA   NA    1    7   NA   NA
    # 3: 2013-05-16   NA    2    3   NA    6    1    7    8    9
    # 4: 2013-05-30    4   NA    3   NA   NA    1   NA   NA   NA
    
    ## to order by column
    temp2 <- as.data.table(reshape(temp[order(V1)], timevar = "V1", v.names = "V1", idvar = "Date", direction = "wide"))
             # Date V1.1 V1.2 V1.3 V1.4 V1.5 V1.6 V1.7 V1.8 V1.9
    # 1: 2013-05-09    1   NA    3    4   NA   NA    7   NA   NA
    # 2: 2013-05-16    1    2    3   NA   NA    6    7    8    9
    # 3: 2013-05-30    1   NA    3    4   NA   NA   NA   NA   NA
    # 4: 2013-05-04   NA    2    3    4    5    6   NA   NA   NA
    
    ##converts to logical true/false
    temp2[,lapply(.SD,function(x) {x[is.na(x)] <- 0; as.logical(x)}), by = Date]
           # Date   vv  V1.1  V1.2 V1.3  V1.4  V1.5  V1.6  V1.7  V1.8  V1.9
    # 1: 2013-05-09 TRUE  TRUE FALSE TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE
    # 2: 2013-05-16 TRUE  TRUE  TRUE TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
    # 3: 2013-05-30 TRUE  TRUE FALSE TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
    # 4: 2013-05-04 TRUE FALSE  TRUE TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE
    

    reshape2 包更直观一点:

    require(reshape2)
    ## dummy variable for TRUE/FALSE
    temp[,vv := TRUE]
    temp_reshape2 <- as.data.table(dcast(temp, Date ~ V1, value.var = "vv"))
    ## replace NA with FALSE
    temp_reshape2[, lapply(.SD, function(x) {x[is.na(x)] <- FALSE; x}), by = Date]
             # Date     1     2    3     4     5     6     7     8     9
    # 1: 2013-05-04 FALSE  TRUE TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE
    # 2: 2013-05-09  TRUE FALSE TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE
    # 3: 2013-05-16  TRUE  TRUE TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
    # 4: 2013-05-30  TRUE FALSE TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
    

    为了完成,一个蹩脚的解析评估解决方案:

    limits <- temp[,c(min(V1),max(V1))]
    sapply(temp[,min(V1) : max(V1)], function(x) {
    temp[,eval(parse(text=paste0("M",x," := any(abs(V1 - ",x,") < .Machine$double.eps)"))),by = Date]
    })
    

    【讨论】:

    • 非常感谢您提供的所有样品。这将证明在其他领域非常有用。
    猜你喜欢
    • 2019-10-20
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 2020-06-17
    • 1970-01-01
    相关资源
    最近更新 更多