我面临一个计算列中值中值的问题。我在一列中有数百个值,但我想一次计算一个序列中五个值的中值,并将中值存储在R中的单独数据帧中,然后类似地继续计算,直到可用数据值结束。
问题是有一些值带有#VALUE,并且在计算中值时,如果出现这样的值,即#value并且要取中值的值少于5,则程序应该只取具有任何可用值数的中值。类似地,对于最后一个中值,如果可用于取中值的值少于5个,则应使用可用的值数计算中值。
可以从这里下载带有一列示例数据的.csv文件链接。
文件链接
如果有人能帮我,我将不胜感激。
谢谢
你可以试试这个:
- 按5行的顺序分组
- 用
NA
替换#VALUE!
- 转换为数字
- 用中位数进行总结
Speed %>%
group_by(group5 = rep(row_number(), each=5, length.out = n())) %>%
mutate(speed = ifelse(speed== "#VALUE!", NA, speed)) %>%
type.convert(as.is = TRUE) %>%
summarise(median = median(speed, na.rm = TRUE))
group5 median
<int> <dbl>
1 1 1.32
2 2 -4.97
3 3 -13.1
4 4 -14.3
5 5 6.89
6 6 -2.97
7 7 -11.6
8 8 -16.0
9 9 -18.6
10 10 -19.9
# ... with 72 more rows
为";翻滚窗口";(此处为顶部(与";滚动窗口";(以下,留作后人参考(。仍然使用来自滚动窗口讨论顶部的dat
。
关于#VALUE!
的讨论(远在下面(可能仍然相关,我将在此处包含代码。
基数R
dat$speed <- suppressWarnings(as.numeric(dat$speed))
aggregate(dat$speed, list(grp = (seq_len(nrow(dat)) - 1) %/% 5), FUN = median, na.rm = TRUE)
# grp x
# 1 0 3.4245
# 2 1 -4.9730
dplyr
library(dplyr)
dat %>%
mutate(speed = suppressWarnings(as.numeric(speed))) %>%
group_by(grp = (seq_len(n()) - 1) %/% 5) %>%
summarize(med5 = median(speed, na.rm = TRUE))
# # A tibble: 2 x 2
# grp med5
# <dbl> <dbl>
# 1 0 3.42
# 2 1 -4.97
数据表
library(data.table)
as.data.table(dat)[, speed := suppressWarnings(as.numeric(speed))
][, .(med5 = median(speed, na.rm = TRUE)), by = .(grp = (seq_len(nrow(dat)) - 1) %/% 5)][]
# grp med5
# <num> <num>
# 1: 0 3.4245
# 2: 1 -4.9730
(以下为滚动窗口,除dat
数据的定义外不再相关。(
我从单列帧中复制了前10行,并得到
dat <- structure(list(speed = c(0, 5.534, 1.315, 7.6865, -0.479, -0.4605, -4.311, -4.973, -7.69, -11.669)), row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")
有了这个,基本操作是这样的:
newvec <- zoo::rollmedian(dat$speed, 5)
newvec
# [1] 1.3150 1.3150 -0.4605 -0.4790 -4.3110 -4.9730
请注意,这将创建nrow(dat) - (k - 1)
(20(值,其中k=5
(您的窗口(。一般来说,滚动操作往往会减少,但如果需要,我们可以选择改变这一点。例如,我们可以保持其相同的长度,并用NA
填充末端;要做到这一点,我们可以";对齐";窗口向左、居中或向右:
zoo::rollmedian(dat$speed, 5, fill = NA, align = "left")
# [1] 1.3150 1.3150 -0.4605 -0.4790 -4.3110 -4.9730 NA NA NA NA
zoo::rollmedian(dat$speed, 5, fill = NA, align = "center")
# [1] NA NA 1.3150 1.3150 -0.4605 -0.4790 -4.3110 -4.9730 NA NA
zoo::rollmedian(dat$speed, 5, fill = NA, align = "right")
# [1] NA NA NA NA 1.3150 1.3150 -0.4605 -0.4790 -4.3110 -4.9730
让我展示一下对齐方式如何适合这里。使用align="center"
(默认值(,我们可以看到:
dat$speed
# [1] 0.0000 5.5340 1.3150 7.6865 -0.4790 -0.4605 -4.3110 -4.9730 -7.6900 -11.6690
### `----------------------------------------'
### take the median of these values,
### and then assign that single value here:
### /
### ,---------------'
### /
# [1] NA NA 1.3150 1.3150 -0.4605 -0.4790 -4.3110 -4.9730 NA NA
dat$speed[1:5]
# [1] 0.0000 5.5340 1.3150 7.6865 -0.4790
median(dat$speed[1:5])
# [1] 1.315
对于下一个值,
# [1] 0.0000 5.5340 1.3150 7.6865 -0.4790 -0.4605 -4.3110 -4.9730 -7.6900 -11.6690
### `----------------------------------------'
### take the median of these values,
### and then assign that single value here:
### /
### ,---------------'
### /
# [1] NA NA 1.3150 1.3150 -0.4605 -0.4790 -4.3110 -4.9730 NA NA
dat$speed[2:6]
# [1] 5.5340 1.3150 7.6865 -0.4790 -0.4605
median(dat$speed[2:6])
# [1] 1.315
因此,我们可以很容易地将其分配给具有data.frame(rollmed = newvec)
的新帧,无论是否填充。如果你想把它分配回原始帧,可以这样做:
dat$rollmed <- zoo::rollmedian(dat$speed, 5, fill = NA, align = "center")
dat
# speed rollmed
# 1 0.0000 NA
# 2 5.5340 NA
# 3 1.3150 1.3150
# 4 7.6865 1.3150
# 5 -0.4790 -0.4605
# 6 -0.4605 -0.4790
# 7 -4.3110 -4.3110
# 8 -4.9730 -4.9730
# 9 -7.6900 NA
# 10 -11.6690 NA
对于您的#VALUE!
,它可能显示为character
列,而不是numeric
,在这种情况下,您在以上所有内容之前有一个额外的步骤。
我将把我的一个值更改为那个错误:
dat$speed[5] <- "#VALUE!"
dat
# speed
# 1 0
# 2 5.534
# 3 1.315
# 4 7.6865
# 5 #VALUE!
# 6 -0.4605
# 7 -4.311
# 8 -4.973
# 9 -7.69
# 10 -11.669
str(dat)
# 'data.frame': 10 obs. of 1 variable:
# $ speed: chr "0" "5.534" "1.315" "7.6865" ...
(参见?chr
。(
从这里,我们可以简单地将所有转换为数字,忽略我们得到的警告:
dat$speed <- suppressWarnings(as.numeric(dat$speed))
dat
# speed
# 1 0.0000
# 2 5.5340
# 3 1.3150
# 4 7.6865
# 5 NA
# 6 -0.4605
# 7 -4.3110
# 8 -4.9730
# 9 -7.6900
# 10 -11.6690
str(dat)
# 'data.frame': 10 obs. of 1 variable:
# $ speed: num 0 5.53 1.31 7.69 NA ...
从这里开始,我们可以再次进行滚动中值。注意,NA
我们现在有一些细微的变化:
dat$rollmed <- zoo::rollmedian(dat$speed, 5, fill = NA, align = "center")
dat$rollmed2 <- zoo::rollmedian(dat$speed, 5, fill = NA, align = "center", na.rm = TRUE)
dat
# speed rollmed rollmed2
# 1 0.0000 NA NA
# 2 5.5340 NA NA
# 3 1.3150 NA 3.42450
# 4 7.6865 NA 3.42450
# 5 NA NA 0.42725
# 6 -0.4605 NA -2.38575
# 7 -4.3110 NA -4.64200
# 8 -4.9730 -4.973 -4.97300
# 9 -7.6900 NA NA
# 10 -11.6690 NA NA
默认情况下(我们之前所做的(将为前一个#VALUE!
的+/-4行(k-1
(内的每一行返回NA
中值;如果您愿意,我们可以添加na.rm=TRUE
;这不是一个滚动窗口的问题,这是一个一般的统计问题,";是否为空值是一个问题";。