【问题标题】:Building a average for a certain timeframe在特定时间范围内建立平均值
【发布时间】:2018-07-03 06:30:48
【问题描述】:

以下问题让我非常头疼。

我有一个看起来像这样的大数据集。

Name   Date         C1   C2    C3    C4    C5    C6   C7
 A     2008-01-03   100
 A     2008-01-05   NA
 A     2008-01-07   120
 A     2008-02-03   NA
 A     2008-03-10   50
 A     2008-07-14   70
 A     2008-07-15   NA
 A     2009-01-03   40
 A     2009-01-05   NA
 A     2010-01-07   NA
 A     2010-03-03   30
 A     2010-03-10   20
 A     2011-07-14   10
 A     2011-07-15   NA
 B     2008-01-03   NA
 B     2008-01-05   5
 B     2008-01-07   3
 B     2008-02-03   11
 B     2008-03-10   13
 B     2008-07-14   ....

如您所见,我的观察中有很多 NA。 其他列看起来相似,数据集有 +100.000 行。所以它很大。

我想要做的是,我想通过以下方式聚合我的数据。 例如 C1: 我想在从 2000 年 1 月到 2012 年 12 月的时间范围内为每个名称以及每年和每个月建立每月平均值。

应使用每个月的可用日期计算月平均值。

计算完成后,我的数据集应如下所示。

Name   Date         C1          C2    C3    C4    C5    C6   C7
 A     2008-01  monthly average
 A     2008-02  monthly average
 A     2008-03  monthly average
 A     2008-04  monthly average
 A     2008-05  monthly average
 A     2008-06  monthly average
 A     2008-07  monthly average
 A     2008-08  monthly average
 A     2008-09  monthly average
 A     2008-10  monthly average
 A     2008-11  monthly average
 A     2008-12  monthly average
 A     2009-01  monthly average

 B     2008-01  monthly average
 B     2008-02  monthly average
 B     2008-03  monthly average
 B     2008-04  monthly average
 B     2008-05  monthly average
 B     2008-06   ....

所以我的输出数据应该显示一年中每个月的每个名称。 如果该月只有 NA 值,则值为 NA,或者它们是该月的月平均值。

例如:

   Name    Date       C1
   A     2008-01-03   100
   A     2008-01-05   NA
   A     2008-01-07   120

这里我们期望:

   Name    Date       C1
   A     2008-01   (100+120)/2 = 110

例如:

   Name    Date       C1
   A     2008-01-03   NA
   A     2008-01-05   NA
   A     2008-01-07   NA

这里我们期望:

    Name    Date       C1
    A     2008-01   NA

例如:

   Name    Date       C1
   A     2008-01-03   100
   A     2008-01-05   50
   A     2008-01-07   120

这里我们期望:

    Name    Date       C1
    A     2008-01    (100+50+120)/3 = 90

由于我对 r 比较陌生并且我不知道如何解决这个问题,我希望找到可以解决这个问题的人并向我展示如何解决这样的问题。 非常感谢您的支持:)

【问题讨论】:

  • 也请分享您的数据。在此处查看更多信息How to make a great R reproducible example?
  • 看看stats 包(即,没有安装)。在将日期格式化为 %Y-%m 之后,您将希望通过(名称,日期)aggregate,然后将 mean 作为函数传递。这应该可以帮助您入门:aggregate(.~Name+MonthDate, data, FUN=mean, na.rm=TRUE).

标签: dataframe


【解决方案1】:
library(dplyr)

#generating sample data 

data <- data.frame(Name = c(rep("A",25), rep("B",50)),
                   Date = seq(as.Date("2018-01-01"), as.Date("2020-01-12"), by = 10),
                   C1 = rep(c(100,NA,NA,NA,NA,500,320,102,412,NA,200,NA,145,800,230),5))

#grouping by Name and Month and summarizing mean of values  

data %>% 
group_by(Name, month = cut(Date, "month")) %>% 
summarise(C1 = mean(C1, na.rm = TRUE)) %>% mutate(C1 = ifelse(is.nan(C1),NA,C1))

【讨论】:

  • 为什么要让 OP 多次输入C1, C2, C3 等?
  • @MKR 你是对的,我会用 summarise_all 而不是 summarise,但我会坚持使用“cut”而不是“format”来从日期中获取月份。这样我们就可以使用它与其他日期对象进行排序和合并
  • @bli12blu12 在 C1 到 C7 的任何字段中是否有非数字数据?您的 NULL 值是否存储为“NA”而不是实际的空值?在这种情况下,您需要使用类似 data$C1[data$C1=="NA"]
【解决方案2】:

您可以dplyr::summarise_all 计算所有列C1C2..等的平均值。

首先在NameYearMon 上设置group_by,然后取消选择Date 列,然后使用summarise_all

library(dplyr)
library(lubridate)

#Added C2 to demonstrate calculation for multiple columns in one go.
df %>% mutate(Date = ymd(Date), C2 = C1*2) %>%  
  group_by(Name, YearMon = format(Date, "%Y-%m")) %>%
  select(-Date) %>%
  summarise_all("mean", na.rm=TRUE)


#OR - Use summarise_at and calculate mean for all columns starting with 'C'
df %>% mutate(Date = ymd(Date), C2 = C1*2) %>% 
  group_by(Name, YearMon = format(Date, "%Y-%m")) %>%
  summarise_at(vars(starts_with("C")), mean, na.rm=TRUE)

# A tibble: 12 x 4
# Groups: Name [?]
   Name  YearMon     C1     C2
   <chr> <chr>    <dbl>  <dbl>
 1 A     2008-01 110    220   
 2 A     2008-02 NaN    NaN   
 3 A     2008-03  50.0  100   
 4 A     2008-07  70.0  140   
 5 A     2009-01  40.0   80.0 
 6 A     2010-01 NaN    NaN   
 7 A     2010-03  25.0   50.0 
 8 A     2011-07  10.0   20.0 
 9 B     2008-01   4.00   8.00
10 B     2008-02  11.0   22.0 
11 B     2008-03  13.0   26.0 
12 B     2008-07 NaN    NaN 

数据:

df <- read.table(text = 
"Name   Date         C1  
A     2008-01-03   100
A     2008-01-05   NA
A     2008-01-07   120
A     2008-02-03   NA
A     2008-03-10   50
A     2008-07-14   70
A     2008-07-15   NA
A     2009-01-03   40
A     2009-01-05   NA
A     2010-01-07   NA
A     2010-03-03   30
A     2010-03-10   20
A     2011-07-14   10
A     2011-07-15   NA
B     2008-01-03   NA
B     2008-01-05   5
B     2008-01-07   3
B     2008-02-03   11
B     2008-03-10   13
B     2008-07-14   NA",
header = TRUE, stringsAsFactors = FALSE)

【讨论】:

  • @bli12blu12 感谢您通知我。它相当容易满足额外的期望。对此也有一个新问题也很好。
猜你喜欢
  • 1970-01-01
  • 2020-03-11
  • 2019-11-09
  • 2021-03-27
  • 1970-01-01
  • 2012-08-02
  • 2017-06-21
  • 2022-11-02
  • 2022-01-11
相关资源
最近更新 更多