【问题标题】:How to add a column with the median value of 5 consecutive rows in r?如何在r中添加具有5个连续行的中值的列?
【发布时间】:2018-04-12 18:13:27
【问题描述】:

我有一张桌子:

ID   Dates        Rates
1  2010-01-01       0
1  2010-01-02       0
1  2010-01-03       2
1  2010-01-04       2
1  2010-01-05       2
1  2010-01-06       1
1  2010-01-07       0
1  2010-01-08       0
1  2010-01-09       0
1  2010-01-10       0
2  2010-01-01       3
2  2010-01-02       3
2  2010-01-03       2

我想在 Rstudio 中计算第三列“中值率”以显示每 5 个连续行的中值,表格应如下所示

ID   Dates       Rates   Median_Rates
1    2010-01-01   0        2
1    2010-01-02   0        2
1    2010-01-03   2        2
1    2010-01-04   2        2
1    2010-01-05   2        2
1    2010-01-06   1        0
1    2010-01-07   0        0
1    2010-01-08   0        0
1    2010-01-09   0        0
1    2010-01-10   0        0
2    2010-01-01   3        3
2    2010-01-02   3        3
2    2010-01-03   2        3

然后将其应用于数据集中的所有 ID 和超过 100 万行?

我想按组 (ID) 计算每连续 5 行(例如此位置 +/- 5 行)的 Rate 的中值,并将其用作 Median_Rates 的值。

【问题讨论】:

  • 我想计算每连续 5 行的 rate 中值(例如这个位置 +/- 5 行),用于计算中值 rate 的值应该是 rate 列中的值。 @divibisan
  • 这称为“滚动中位数”,如果您搜索该术语,您应该会找到大量示例。在zoo::rollapply 中,您可以指定FUN = median

标签: r


【解决方案1】:

使用lubridate 转换为Date 的基于dplyr 的解决方案可以实现为:

library(dplyr)
library(lubridate)

df %>% mutate(Dates = ymd(Dates)) %>%
  group_by(ID) %>%
  arrange(Dates) %>%
  mutate(Group = (row_number()-1) %/% 5 ) %>%
  group_by(ID, Group) %>%
  mutate(Median_Rates = median(Rates)) %>%
  ungroup() %>%
  arrange(ID) %>%
  select(-Group) %>% as.data.frame()

#    ID      Dates Rates Median_Rates
# 1   1 2010-01-01     0            2
# 2   1 2010-01-02     0            2
# 3   1 2010-01-03     2            2
# 4   1 2010-01-04     2            2
# 5   1 2010-01-05     2            2
# 6   1 2010-01-06     1            0
# 7   1 2010-01-07     0            0
# 8   1 2010-01-08     0            0
# 9   1 2010-01-09     0            0
# 10  1 2010-01-10     0            0
# 11  2 2010-01-01     3            3
# 12  2 2010-01-02     3            3
# 13  2 2010-01-03     2            3

【讨论】:

    【解决方案2】:

    函数ave 就是为此而生的。
    我借鉴了the accepted answer to this question的想法,将tapply改为ave,将sum改为median

    data$Median_Rates <- ave(data$Rates, (seq_along(data$Rates)-1) %/% 5, FUN = median)
    data
    #   ID      Dates Rates Median_Rates
    #1   1 2010-01-01     0            2
    #2   2 2010-01-02     0            2
    #3   3 2010-01-03     2            2
    #4   4 2010-01-04     2            2
    #5   5 2010-01-05     2            2
    #6   5 2010-01-06     1            0
    #7   7 2010-01-07     0            0
    #8   8 2010-01-08     0            0
    #9   9 2010-01-09     0            0
    #10 10 2010-01-10     0            0
    

    数据

    data <-
    structure(list(ID = c(1L, 2L, 3L, 4L, 5L, 5L, 7L, 8L, 9L, 10L
    ), Dates = structure(1:10, .Label = c("2010-01-01", "2010-01-02", 
    "2010-01-03", "2010-01-04", "2010-01-05", "2010-01-06", "2010-01-07", 
    "2010-01-08", "2010-01-09", "2010-01-10"), class = "factor"), 
        Rates = c(0L, 0L, 2L, 2L, 2L, 1L, 0L, 0L, 0L, 0L)), .Names = c("ID", 
    "Dates", "Rates"), class = "data.frame", row.names = c(NA, -10L
    ))
    

    编辑。
    使用新数据集,只需在对 ave 的调用中还包含列 ID 作为分组变量。
    我将把这个新数据集称为data2

    data2$Median_Rates <- ave(data2$Rates, data2$ID, (seq_along(data2$Rates)-1) %/% 5, FUN = median)
    data2
    #   ID      Dates Rates Median_Rates
    #1   1 2010-01-01     0            2
    #2   1 2010-01-02     0            2
    #3   1 2010-01-03     2            2
    #4   1 2010-01-04     2            2
    #5   1 2010-01-05     2            2
    #6   1 2010-01-06     1            0
    #7   1 2010-01-07     0            0
    #8   1 2010-01-08     0            0
    #9   1 2010-01-09     0            0
    #10  1 2010-01-10     0            0
    #11  2 2010-01-01     3            3
    #12  2 2010-01-02     3            3
    #13  2 2010-01-03     2            3
    

    新数据

    data2 <-
    structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    2L, 2L, 2L), Dates = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 
    8L, 9L, 10L, 1L, 2L, 3L), .Label = c("2010-01-01", "2010-01-02", 
    "2010-01-03", "2010-01-04", "2010-01-05", "2010-01-06", "2010-01-07", 
    "2010-01-08", "2010-01-09", "2010-01-10"), class = "factor"), 
        Rates = c(0L, 0L, 2L, 2L, 2L, 1L, 0L, 0L, 0L, 0L, 3L, 3L, 
        2L)), .Names = c("ID", "Dates", "Rates"), class = "data.frame", row.names = c(NA, 
    -13L))
    

    【讨论】:

    • @Y.Yuan 您要求“每连续 5 行”中位数(在您的评论中)。我的第一个答案就是这样做的。然后,您使用新数据编辑了问题。我会看看我能做什么。
    • @Y.Yuan 完成,以dput 格式查看编辑和新数据集。
    猜你喜欢
    • 2015-07-01
    • 2022-10-05
    • 2016-09-10
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 2022-06-28
    • 2021-02-04
    • 2019-11-15
    相关资源
    最近更新 更多