【发布时间】:2016-11-24 09:17:06
【问题描述】:
我有一个大数据框,其中包含由多个探针执行的不同测量。
测量的时间并不完全相同。由于我想在给定时间比较两个测量值并将它们绘制在动画中,因此我需要“同步”我的数据。
这是我得到的数据框示例(在现实生活中,我有更多的列可以直接从文本文件中读取):
time1.in.s <- seq(0.010, 100, length.out = 100)
time2.in.s <- seq(0.022, 100, length.out = 100)
data1 <- seq(-10, 100, length.out = 100)
data2 <- seq(-25, 80, length.out = 100)
my.df <- data.frame(time1.in.s, data1, time2.in.s, data2)
这给出了:
time1.in.s data1 time2.in.s data2
1 0.01 -10.000000 0.022000 -25.0000000
2 1.02 -8.888889 1.031879 -23.9393939
3 2.03 -7.777778 2.041758 -22.8787879
4 3.04 -6.666667 3.051636 -21.8181818
5 4.05 -5.555556 4.061515 -20.7575758
6 5.06 -4.444444 5.071394 -19.6969697
我想要做的是将两个 timeX.in.s 列合并到一个“时间”列中。如果数据不可用,我会使用类似na.approx(my.df$data1, x = my.df$time) 的内容填写 NA。
给出此代码是为了重现问题,但在现实生活中,time1.in.s、time2.in.s、data1 和 data2 不能单独使用。我实际上做的是my.df <- read.table(my.file, header = TRUE),我得到了相同的结果。因此我无法直接构建单独的数据框,我需要手动将一个大数据框拆分为多个:
df.list <- list()
for (i in seq(1, ncol(my.df), 2)) {
df.list[[ceiling(i/2)]] <- data.frame(time = my.df[, i], data = my.df[, i+1])
}
然后将数据帧一一合并:
merged.df <- data.frame(time = as.numeric(NA), data = as.numeric(NA))
for (i in 1:length(df.list)) {
merged.df <- merge(merged.df, df.list[[i]], by = "time", all = TRUE)
}
最后填补空白:
merged.df$data.y <- na.approx(merged.df$data.y, x = merged.df$time, na.rm = FALSE)
这绝对有效(除了列名很乱)。但这很麻烦,对我来说看起来不是很R。有没有更简单的方法来做到这一点?
这是使用上述命令得到的结果:
> head(merged.df)
time data.x data.y data
1 0.010000 NA -10.000000 NA
2 0.022000 NA -9.986799 -25.00000
3 1.020000 NA -8.888889 NA
4 1.031879 NA -8.875821 -23.93939
5 2.030000 NA -7.777778 NA
6 2.041758 NA -7.764843 -22.87879
列 data.x 来自最初的空 merge.df。它可以被丢弃。 列 data.y 是 my.df$data1 列。 在上面的数据框中,我没有对列数据使用 na.approx 命令(对应于 my.df$data2 列)
关于 OmaymaS 提出的解决方案的补充说明:
为了在一般情况下(即使用任意数量的列)进行这项工作,我所做的如下。首先,我定义了一个 6 列的数据框:
time1.in.s <- seq(0.010, 100, length.out = 100)
time2.in.s <- seq(0.022, 100, length.out = 100)
time3.in.s <- seq(0.017, 99.8, length.out = 100)
data1 <- seq(-10, 100, length.out = 100)
data2 <- seq(-25, 80, length.out = 100)
data3 <- seq(-15, 70, length.out = 100)
my.df <- data.frame(time1.in.s, data1, time2.in.s, data2, time3.in.s, data3)
这导致:
head(my.df)
time1.in.s data1 time2.in.s data2 time3.in.s data3
1 0.01 -10.000000 0.022000 -25.00000 0.017000 -15.00000
2 1.02 -8.888889 1.031879 -23.93939 1.024909 -14.14141
3 2.03 -7.777778 2.041758 -22.87879 2.032818 -13.28283
4 3.04 -6.666667 3.051636 -21.81818 3.040727 -12.42424
5 4.05 -5.555556 4.061515 -20.75758 4.048636 -11.56566
6 5.06 -4.444444 5.071394 -19.69697 5.056545 -10.70707
我将包含时间的所有列的名称更改为相同的名称(这样我就不必告诉merge 函数要合并哪个列by):
colnames(my.df)[seq(1, ncol(my.df), 2)] <- "Time"
然后我循环一个稍微修改的 Reduce 函数:
df.merged <- my.df[, 1:2]
for (i in seq(3, ncol(my.df), 2)) {
df.merged <- Reduce(function(x,y) merge(x,y,
all = TRUE),
list(df.merged,
my.df[, i:(i+1)])
)
}
这给出了:
> head(df.merged)
Time data1 data2 data3
1 0.010000 -10.000000 NA NA
2 0.017000 NA NA -15.00000
3 0.022000 NA -25.00000 NA
4 1.020000 -8.888889 NA NA
5 1.024909 NA NA -14.14141
6 1.031879 NA -23.93939 NA
最后,我应用na.approx函数:
df.interp <- df.merged
df.interp[, 2:ncol(df.interp)] <- na.approx(df.interp[, 2:ncol(df.interp)],
x = df.interp$Time,
na.rm = FALSE)
这是最终结果:
> head(df.interp)
Time data1 data2 data3
1 0.010000 -10.000000 NA NA
2 0.017000 -9.992299 NA -15.00000
3 0.022000 -9.986799 -25.00000 -14.99574
4 1.020000 -8.888889 -23.95187 -14.14560
5 1.024909 -8.883488 -23.94671 -14.14141
6 1.031879 -8.875821 -23.93939 -14.13548
我仍然在一些数据列的开头有 NA,但我可以使用 na.omit 函数将它们删除。
【问题讨论】:
-
您能否提供最终结果的前 5 行,因为您提供的代码无法满足您的需求。
-
相应地编辑了问题