R 将时间序列中的重复行与数据表中的不同列类型组合在一起

Bol*_*lle 9 datatable aggregate r time-series

这个问题建立在另一个问题R 上,将重复行按 ID 与数据帧中的不同列类型组合在一起。我有一个包含一列time和其他一些不同类型(因子和数字)列的数据表。下面是一个例子:

dt <- data.table(time  = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4),
             abst  = c(0, NA, 2, NA, NA, NA, 0, 0, NA, 2, NA, 3, 4),
             farbe = as.factor(c("keine", NA, "keine", NA, NA, NA, "keine", "keine", NA, NA, NA, "rot", "blau")),
             gier  = c(0, NA, 5, NA, NA, NA, 0, 0, NA, 1, NA, 6, 2),
             goff  = as.factor(c("haus", "maus", "toll", NA, "haus", NA, "maus", NA, NA, NA, NA, NA, "maus")),
             huft  = as.factor(c(NA, NA, NA, NA, NA, "wolle", NA, NA, "wolle", NA, NA, "holz", NA)),
             mode  = c(4, 2, NA, NA, 6, 5, 0, NA, NA, NA, NA, NA, 3))
Run Code Online (Sandbox Code Playgroud)

现在我想合并 column 中的重复时间time。数字列被定义为所有相同 ID(没有 NA!)的平均值。因子列合并为一个。NA 可以省略。

dtRes <- data.table(time  = c(1, 1, 1, 2, 3, 4, 4),
                abst  = c(1, 1, 1, 0, 0, 3, 3),
                farbe = as.factor(c("keine", "keine", "keine", "keine", "keine", "rot", "blau")),
                gier  = c(2.5, 2.5, 2.5, 0, 0, 3, 3),
                goff  = as.factor(c("haus", "maus", "toll", "maus", NA, "maus", "maus")),
                huft  = as.factor(c(NA, NA, NA, "wolle", "wolle", "holz", "holz")),
                mode  = c(4, 4, 4, 2.5, NA, 3, 3))
Run Code Online (Sandbox Code Playgroud)

我需要为此进行一些快速计算,因为我有大约一百万个观察结果。

对这个问题的一些额外想法:farbe可能不是唯一的。在这种情况下,我认为我的数据最好的主意是有一个重复的行,但只有一个不同的行farbe,所以有 2 个相同的时间,其余的都保持不变,但farbe. 这应该是非常罕见的情况,但将是一个很好的补充。

另外:我的真实数据中有更多的数字和因子列,所以我不想单独定义每一列。在某些数据表中没有因子列。因此,即使没有数字(time总是存在和数字)或因子列,该解决方案也必须有效。

提前谢谢!

akr*_*run 7

我们可以做一个小组 mean

library(data.table)
library(tidyr)
library(dplyr)
dt[, lapply(.SD, function(x) if(is.numeric(x)) mean(x, na.rm = TRUE)
     else toString(unique(x[!is.na(x)]))), .(time)] %>%
     separate_rows(farbe, goff)
# A tibble: 7 x 7
#   time  abst farbe  gier goff   huft     mode
#  <dbl> <dbl> <chr> <dbl> <chr>  <chr>   <dbl>
#1     1     1 keine   2.5 "haus" ""        4  
#2     1     1 keine   2.5 "maus" ""        4  
#3     1     1 keine   2.5 "toll" ""        4  
#4     2     0 keine   0   "maus" "wolle"   2.5
#5     3     0 keine   0   ""     "wolle" NaN  
#6     4     3 rot     3   "maus" "holz"    3  
#7     4     3 blau    3   "maus" "holz"    3  
Run Code Online (Sandbox Code Playgroud)

或与 cSplit

library(splitstackshape)
cSplit(dt[, lapply(.SD, function(x) if(is.numeric(x)) 
    mean(x, na.rm = TRUE) else toString(unique(x[!is.na(x)]))), .(time)], 
    c('farbe', 'goff'), sep= ',\\s*', 'long', fixed = FALSE)
#   time abst farbe gier goff  huft mode
#1:    1    1 keine  2.5 haus        4.0
#2:    1    1  <NA>  2.5 maus        4.0
#3:    1    1  <NA>  2.5 toll        4.0
#4:    2    0 keine  0.0 maus wolle  2.5
#5:    3    0 keine  0.0 <NA> wolle  NaN
#6:    4    3   rot  3.0 maus  holz  3.0
#7:    4    3  blau  3.0 <NA>  holz  3.0
Run Code Online (Sandbox Code Playgroud)


Uwe*_*Uwe 3

无需后续调用separate_rows()或也可以实现预期结果(对于给定的示例数据集)cSplit()

library(data.table) # version 1.12.9
dt[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE) 
            else unlist(na.omit(unique(x)))), by = time]

   time abst farbe gier goff  huft mode
1:    1    1 keine  2.5 haus  <NA>  4.0
2:    1    1 keine  2.5 maus  <NA>  4.0
3:    1    1 keine  2.5 toll  <NA>  4.0
4:    2    0 keine  0.0 maus wolle  2.5
5:    3    0 keine  0.0 <NA> wolle  NaN
6:    4    3   rot  3.0 maus  holz  3.0
7:    4    3  blau  3.0 maus  holz  3.0
Run Code Online (Sandbox Code Playgroud)

请注意,此方法适用于数字列和因子列的任意组合;不需要明确说明列名。


但是,我确实相信根本问题的正确答案是返回一行而time不是一种部分聚合(当然,您的里程可能会有所不同):

dt[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE) 
                   else list(na.omit(unique(x)))), by = time]
Run Code Online (Sandbox Code Playgroud)
   time abst    farbe gier           goff  huft mode
1:    1    1    keine  2.5 haus,maus,toll        4.0
2:    2    0    keine  0.0           maus wolle  2.5
3:    3    0    keine  0.0                wolle  NaN
4:    4    3 rot,blau  3.0           maus  holz  3.0
Run Code Online (Sandbox Code Playgroud)

请注意,list()代替toString()已用于聚合因子列。,这样做的好处是可以避免在因子级别之一偶然包含逗号时出现问题。time此外,在大型生产数据集中识别具有非唯一因素的案例更容易:

# compute aggregate as before
dtRes <- dt[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE) 
                   else list(na.omit(unique(x)))), by = time]
# find cases with non-unique factors per group
# note .SDcols = is.list is available with data.table version 1.12.9
tmp <- dtRes[, which(Reduce(sum, lapply(.SD, function(x) lengths(x) > 1L)) > 0), .SDcols = is.list, by = time]
tmp
Run Code Online (Sandbox Code Playgroud)
   time V1
1:    1  1
2:    4  1
Run Code Online (Sandbox Code Playgroud)
# show affected rows
dtRes[tmp, on = "time"]
Run Code Online (Sandbox Code Playgroud)
   time abst    farbe gier           goff huft mode V1
1:    1    1    keine  2.5 haus,maus,toll         4  1
2:    4    3 rot,blau  3.0           maus holz    3  1
Run Code Online (Sandbox Code Playgroud)
# show not affected rows
dtRes[!tmp, on = "time"]
Run Code Online (Sandbox Code Playgroud)
   time abst farbe gier goff  huft mode
1:    2    0 keine    0 maus wolle  2.5
2:    3    0 keine    0      wolle  NaN
Run Code Online (Sandbox Code Playgroud)