按R顺序计算列的中值,并将值存储在数据帧中



我面临一个计算列中值中值的问题。我在一列中有数百个值,但我想一次计算一个序列中五个值的中值,并将中值存储在R中的单独数据帧中,然后类似地继续计算,直到可用数据值结束。

问题是有一些值带有#VALUE,并且在计算中值时,如果出现这样的值,即#value并且要取中值的值少于5,则程序应该只取具有任何可用值数的中值。类似地,对于最后一个中值,如果可用于取中值的值少于5个,则应使用可用的值数计算中值。

可以从这里下载带有一列示例数据的.csv文件链接。

文件链接

如果有人能帮我,我将不胜感激。

谢谢

你可以试试这个:

  1. 按5行的顺序分组
  2. NA替换#VALUE!
  3. 转换为数字
  4. 用中位数进行总结
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;这不是一个滚动窗口的问题,这是一个一般的统计问题,";是否为空值是一个问题";。

最新更新