我试图将一个数据表的不规则时间序列转换为常规时间序列。我的数据是这样的
library(data.table)
dtRes <- data.table(time = c(0.1, 0.8, 1, 2.3, 2.4, 4.8, 4.9),
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))
怎么可能把观测值分块汇总,取一个类似1秒的分块大小,(行数可变--如果1秒内没有行,甚至为0)结果应该是数字列的平均值(省略NAs),对于因子来说,如果有1个以上的唯一值,则是整整重复的一行。如果对于因子不可能或者你觉得不合理,也可以只取因子列中特定秒的第一个值。这样就会是真正的规律性时间序列,没有任何重复的时间。如果一个区间没有值(比如例子中的第2秒),结果就是NA。
最后的结果可以是这样的(取决于是否有重复的行)。
有重复的:
wiDups <- data.table(time = c(1, 1, 2, 3, 4, 5, 5),
abst = c(1, 1, NA, 1, NA, 5, 5),
farbe = as.factor(c("keine", "keine", NA, "keine", NA, "rot", "blau")),
gier = c(2.5, 2.5, NA, 0, NA, 4.5, 4.5),
goff = as.factor(c("haus", "maus", NA, "maus", NA, "maus", "maus")),
huft = as.factor(c(NA, NA, NA, "wolle", NA, "holz", "holz")),
mode = c(5, 5, NA, 2.5, NA, 4, 4))
和没有重复的。
noDups <- data.table(time = c(1, 2, 3, 4, 5),
abst = c(1, NA, 1, NA, 5),
farbe = as.factor(c("keine", NA, "keine", NA, "rot")),
gier = c(2.5, NA, 0, NA, 4.5),
goff = as.factor(c("haus", NA, "maus", NA, "maus")),
huft = as.factor(c(NA, NA, "wolle", NA, "holz")),
mode = c(5, NA, 2.5, NA, 4))
把它转换成一个时间序列对象会更好吗?
这个问题是对OP的问题的追问 R将时间序列中的重复行与数据化的不同列类型结合起来。.
上诉人要求通过汇总将一个不规则的时间序列变成一个常规的时间序列。
这可以通过汇总并通过右连接来填补缺失的值来实现。
win <- 1 # step size of time series or length of time window
brk <- dtRes[, .(time = tail(scales::fullseq(range(time), win), -1L))]
dtRes[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE)
else unlist(na.omit(unique(x)))),
by = .(time = ceiling(time / win) * win)][
brk, on = .(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 NA <NA> NA <NA> <NA> NA 5: 3 0 keine 0.0 maus wolle 2.5 6: 4 NA <NA> NA <NA> <NA> NA 7: 5 3 rot 3.0 maus holz 3.0 8: 5 3 blau 3.0 maus holz 3.0
为了创建常规时间序列: fullseq()
来自 scales
包是为了方便使用。显然,上位机更喜欢右封闭的区间,所以第一个值可以跳过。
警告信息
在
`[.data.table`(dtRes, , lapply(.SD, function(x) if (is.numeric(x)) mean(x,
: j的第1组结果第5项长度为零。这将用3个新的注册会计师来填充,以匹配该结果中最长的一列。 后面的组可能会有类似的问题,但只有第一组会被报告,以节省填充警告缓冲区的时间。
可以愉快地忽略。
发出警告的原因是 huft
是 NA
对于 time == 1
. 呼叫后 na.omit()
的结果向量。huft
列是空的,但组结果有3行。所以: data.table
将结果向量填充为 NA
得到一个匹配的长度--这正是我们所期望的。
该解决方案的参数化是为了适应不同的分块大小。win
. 对于大小为 win <- 0.5
例如,我们得到
time abst farbe gier goff huft mode 1: 0.5 1 keine 2.5 haus <NA> 4.0 2: 1.0 1 keine 2.5 maus <NA> 4.0 3: 1.0 1 keine 2.5 toll <NA> 4.0 4: 1.5 NA <NA> NA <NA> <NA> NA 5: 2.0 NA <NA> NA <NA> <NA> NA 6: 2.5 0 keine 0.0 maus wolle 2.5 7: 3.0 NA <NA> NA <NA> <NA> NA 8: 3.5 NA <NA> NA <NA> <NA> NA 9: 4.0 NA <NA> NA <NA> <NA> NA 10: 4.5 NA <NA> NA <NA> <NA> NA 11: 5.0 3 rot 3.0 maus holz 3.0 12: 5.0 3 blau 3.0 maus holz 3.0
有更多的行要填。
对于一个大小为 win <- 2
我们得到
time abst farbe gier goff huft mode 1: 2 1 keine 2.5 haus <NA> 4.0 2: 2 1 keine 2.5 maus <NA> 4.0 3: 2 1 keine 2.5 toll <NA> 4.0 4: 4 0 keine 0.0 maus wolle 2.5 5: 6 3 rot 3.0 maus holz 3.0 6: 6 3 blau 3.0 maus holz 3.0
每个时间间隔有多行的时间序列为 不 一个有规律的时间序列,IMHO。稍微修改一下,我们就可以得到。
win <- 1
brk <- dtRes[, .(time = scales::fullseq(range(time), win)[-1L])]
dtRes[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE)
else list(na.omit(unique(x)))),
by = .(time = ceiling(time / win) * win)][
brk, on = .(time)]
time abst farbe gier goff huft mode 1: 1 1 keine 2.5 haus,maus,toll 4.0 2: 2 NA NA NA 3: 3 0 keine 0.0 maus wolle 2.5 4: 4 NA NA NA 5: 5 3 rot,blau 3.0 maus holz 3.0
现在,每个时间步只有一行,因为多个因子的值已经聚集在一个列表元素中。
下面是一个 data.table
答。
四舍五入 time
到最近的秒。
> dtRes[,
+ lapply(.SD, function(z) {return(ifelse(is.factor(z), levels(z)[unique(z)[1]], mean(z, na.rm = T)))} ),
+ by = .(time = round(time, digits = 0))]
time abst farbe gier goff huft mode
1: 0 1 keine 2.5 haus <NA> 4.0
2: 1 1 keine 2.5 maus <NA> 4.0
3: 2 0 keine 0.0 maus wolle 2.5
4: 5 3 rot 3.0 maus holz 3.0
使用... ceiling
函数。
> dtRes[,
+ lapply(.SD, function(z) {return(ifelse(is.factor(z), levels(z)[unique(z)[1]], mean(z, na.rm = T)))} ),
+ by = .(time = ceiling(time))]
time abst farbe gier goff huft mode
1: 1 1 keine 2.5 haus <NA> 4.0
2: 3 0 keine 0.0 maus wolle 2.5
3: 5 3 rot 3.0 maus holz 3.0
你可以调整返回的逻辑 level
根据你想要的东西。在这里,我还 level
对应于第一个非唯一值。
您可以切换到使用 as.numeric
在 ifelse
语句--结果类似。我意识到数据类型为 factor
栏目变更为 character
- 如果您需要 factor
那么你可以在一个单独的语句中专门设置,或者使用链式。
dtRes[, lapply(.SD, ....), by = .(....)][, lapply(.SD, as.factor(...)), .SDcols = .( columns you want as factors), ]
不完全确定你想做什么,但如果我理解正确的话,类似这样。
dtRes %>%
group_by(second = ceiling(time)) %>%
summarise(abst = mean(abst),
farbe = farbe[1],
gier = mean(gier),
goff = goff[1],
huft = huft[1],
mode = mean(mode)) %>%
add_row(second = c(1:10)[!(c(1:10) %in% .$second)]) %>% #change 10 to however many seconds you will have
arrange(second)
# A tibble: 10 x 7
second abst farbe gier goff huft mode
<dbl> <dbl> <fct> <dbl> <fct> <fct> <dbl>
1 1 1 keine 2.5 haus NA 4
2 2 NA NA NA NA NA NA
3 3 0 keine 0 maus wolle NA
4 4 NA NA NA NA NA NA
5 5 3 rot 3 maus holz 3
6 6 NA NA NA NA NA NA
7 7 NA NA NA NA NA NA
8 8 NA NA NA NA NA NA
9 9 NA NA NA NA NA NA
10 10 NA NA NA NA NA NA
请注意,从你的例子中看不出你是如何把时间四舍五入到秒的, 但我想你总是想四舍五入?