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总是存在和数字)或因子列,该解决方案也必须有效。
提前谢谢!
我们可以做一个小组 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)
无需后续调用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)
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
请注意,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)
Run Code Online (Sandbox Code Playgroud)time V1 1: 1 1 2: 4 1
# show affected rows
dtRes[tmp, on = "time"]
Run Code Online (Sandbox Code Playgroud)
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
# show not affected rows
dtRes[!tmp, on = "time"]
Run Code Online (Sandbox Code Playgroud)
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