我在R中有一个如下所示的数据框:
Date | Time | value
A | 1 | 3
A | 1 | 6
A | 2 | 4
A | 3 | 3
A | 4 | 2
A | 5 | 7
B | 1 | 6
B | 2 | 5
B | 2 | 3
B | 2 | 4
B | 3 | 2
B | 5 | 3
B | 6 | 4
...
如果第二列中的数字在连续的行中相等,我的目的是找到第三列中数字的中位数。即,如果它们同时出现,则取值的中位数,并替换该对应时间段的中值。
所以输出我的目标是:
A | 1 | median (3,6)
A | 2 | 4
A | 3 | 3
A | 4 | 2
A | 5 | 7
B | 1 | 6
B | 2 | median (3,4,5)
B | 3 | 2
B | 5 | 3
B | 6 | 4
...
我拼命想避免循环,因为数据集很大。我遇到的主要问题是分别收集值。这是我到目前为止所做的:
#First find consecutive time slots that are equal:
timeslots_equal<-which(diff(data_RAW$TIME)==0)
coordinates_placesholder <- sort(c(as.vector(timestamp_equal_coordinates), as.vector(timestamp_equal_coordinates)+1))
coordinates_placesholder2 <- coordinates_placesholder[-c(which(diff(coordinates_placesholder)==0), which(diff(coordinates_placesholder)==0) +1)]
#The following matrix are the coordinates in the value vector with equal time slots
matrix_ranges<-t(matrix(coordinates_placesholder2,2))
上面示例的 matrix_ranges
如下所示:
1 | 2
8 | 10
然后我尝试应用类似
的内容median(data_RAW$Value[matrix_ranges[,1]:matrix_ranges[,2]])
这不起作用。这样做有人有任何答案吗?
还有一种比我上面做的更简单的方法吗?
答案 0 :(得分:2)
我想到了两种解释。
解释1:重要的是“日期”+“时间”的组合,而不是连续的重复。在这种情况下,只需使用aggregate
(或您最喜欢的聚合函数或包,如“data.table”)。
aggregate(value ~ Date + Time, mydf, median)
# Date Time value
# 1 A 1 4.5
# 2 B 1 6.0
# 3 A 2 4.0
# 4 B 2 4.0
# 5 A 3 3.0
# 6 B 3 2.0
# 7 A 4 2.0
# 8 A 5 7.0
# 9 B 5 3.0
# 10 B 6 4.0
解释2:连续重复 非常重要。在这种情况下,您需要另一个“分组”变量。为此,我们可以使用rle
。之后,聚合步骤几乎相同。
RLE <- rle(DF$Time)$lengths
RLE <- rep(seq_along(RLE), RLE)
aggregate(value ~ Date + Time + RLE, DF, median)
# Date Time RLE value
# 1 A 1 1 4.5
# 2 A 2 2 4.0
# 3 A 3 3 3.0
# 4 A 4 4 2.0
# 5 A 5 5 7.0
# 6 B 1 6 6.0
# 7 B 2 7 4.0
# 8 B 3 8 2.0
# 9 B 5 9 3.0
# 10 B 6 10 4.0
# 11 A 1 11 3.0
# 12 B 3 12 2.0
为了他人的利益,这里有一些可重现的数据:mydf
和DF
。 (DF
只是mydf
,重复了几行。)
mydf <- structure(list(Date = c("A", "A", "A", "A", "A", "A", "B", "B",
"B", "B", "B", "B", "B"), Time = c(1L, 1L, 2L, 3L, 4L, 5L, 1L,
2L, 2L, 2L, 3L, 5L, 6L), value = c(3L, 6L, 4L, 3L, 2L, 7L, 6L,
5L, 3L, 4L, 2L, 3L, 4L)), .Names = c("Date", "Time", "value"),
class = "data.frame", row.names = c(NA, -13L))
DF <- rbind(mydf, mydf[c(1, 1, 11, 11), ])