R: суммировать строки в месяц - PullRequest
1 голос
/ 03 ноября 2019

Я создал фрейм данных, в котором есть столбец с датами и столбцы с числовыми значениями. Я хочу, чтобы этот фрейм данных группировался сам по месяцам и суммировал все числовые значения из других столбцов за соответствующий месяц.

Вот мой пример фрейма данных:

capture.date  Test1  Test2  Test3
2016-03-18      0      1      1
2016-03-18      1      1      1
2016-03-20      2      1      1
2016-04-12      1      0      1

Я уже попробовал некоторый код:

df %>% 
  group_by(capture.date) %>% 
  summarise_each(funs(sum))

и:

aggregate(df[2:4], by=df["capture.date"], sum)

, но оба этих параметра возвращают фреймы данных, которые суммируются по дням, а не по месяцам. Как я могу сделать это суммировать по месяцам, а не по дням?

желаемый результат:

capture.date  Test1  Test2  Test3
2016-03         3      3      3     
2016-04         1      0      1

Ответы [ 3 ]

3 голосов
/ 03 ноября 2019

1) dplyr / zoo Используя воспроизводимые в примечании данные в конце, преобразуйте каждую дату в класс yearmon, который представляет даты без дня, а затем суммируйте числовые столбцы:

library(dplyr)
library(zoo)

df %>% 
  group_by(yearmon = as.yearmon(capture.date)) %>% 
  summarize_if(is.numeric, sum) %>%
  ungroup

дает этот тибл:

# A tibble: 2 x 4
  yearmon   Test1 Test2 Test3
  <yearmon> <int> <int> <int>
1 Mar 2016      3     3     3
2 Apr 2016      1     0     1

2) зоопарк Это можно сделать поочередно с помощью команды singhle read.zoo. fortify.zoo может быть использовано для результата, если вы хотите, чтобы в результате получился data.frame:

library(zoo)
read.zoo(df, FUN = as.yearmon, aggregate = sum)

, дающий эту серию зоопарка:

         Test1 Test2 Test3
Mar 2016     3     3     3
Apr 2016     1     0     1

2a) зоопарк сТрубопровод magrittr Этот вариант можно записать как этот конвейер с конвейером magrittr (или dplyr):

library(magrittr)
library(zoo)

df %>% read.zoo(FUN = as.yearmon, aggregate = sum)

или преобразовать в data.frame

library(magrittr)
library(zoo)

df %>% read.zoo(FUN = as.yearmon, aggregate = sum) %>% fortify.zoo

3) Base R Используя только Base R, извлеките первые 7 символов каждой даты, а затем агрегируйте по ним:

df2 <- transform(df, year.month = substr(capture.date, 1, 7), capture.date = NULL)
aggregate(. ~ year.month, df2, sum)

, предоставив эти данные. Frame:

  year.month Test1 Test2 Test3
1    2016-03     3     3     3
2    2016-04     1     0     1

Примечание

Ввод в воспроизводимой форме:

Lines <- "
capture.date  Test1  Test2  Test3
2016-03-18      0      1      1
2016-03-18      1      1      1
2016-03-20      2      1      1
2016-04-12      1      0      1"
df <- read.table(text = Lines, header = TRUE, as.is = TRUE)
3 голосов
/ 03 ноября 2019

Следующее должно работать

library(lubridate)
library(tidyverse)

txt <- "capture.date  Test1  Test2  Test3
2016-03-18      0      1      1
2016-03-18      1      1      1
2016-03-20      2      1      1
2016-04-12      1      0      1"

data <- read.table(text = txt, header = TRUE)

data %>% 
  mutate(month = month(capture.date), 
         year = year(capture.date)) %>% 
  group_by(month, year) %>% 
  summarise_if(is.integer, sum) %>%
  ungroup %>%
  mutate("capture.date" = paste(year, str_pad(month, 2, side = "left", pad = "0"), sep = "-")) %>%
  select(capture.date, Test1, Test2, Test3)

Это приведет к

# A tibble: 2 x 4
  capture.date Test1 Test2 Test3
  <chr>        <int> <int> <int>
1 2016-03          3     3     3
2 2016-04          1     0     1

Вам может потребоваться изменить функцию в summarise_if на что-то другое, чем is.integer для ваших реальных данных.

2 голосов
/ 03 ноября 2019

Вы можете извлечь даты в формате %Y-%m в group_by() и использовать summarise_if() или summarise_at(), чтобы выбрать, какие переменные будут суммироваться.

(Подтвердите, что capture.date равно Dateкласс)

df %>%
  group_by(Date = strftime(capture.date, "%Y-%m")) %>%
  summarise_if(is.numeric, sum)

# # A tibble: 2 x 4
#   Date    Test1 Test2 Test3
#   <chr>   <int> <int> <int>
# 1 2016-03     3     3     3
# 2 2016-04     1     0     1
...