2016-08-03 3 views
0

Я пытаюсь обобщить набор данных по нескольким различным факторам. Ниже приведен пример моих данных:Подведение данных по дате и группе

household<-c("household1","household1","household1","household2","household2","household2","household3","household3","household3") 
date<-c(sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 9)) 
value<-c(1:9) 
type<-c("income","water","energy","income","water","energy","income","water","energy") 
df<-data.frame(household,date,value,type) 

    household  date value type 
1 household1 1999-05-10 100 income 
2 household1 1999-05-25 200 water 
3 household1 1999-10-12 300 energy 
4 household2 1999-02-02 400 income 
5 household2 1999-08-20 500 water 
6 household2 1999-02-19 600 energy 
7 household3 1999-07-01 700 income 
8 household3 1999-10-13 800 water 
9 household3 1999-01-01 900 energy 

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

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

ddply(df,.(shortdate),summarize,mean_value=mean(value)) 
    shortdate mean_value 
1  14/07 15.88235 
2  14/09 5.00000 
3  14/10 5.00000 
4  14/11 21.81818 
5  14/12 20.00000 
6  15/01 10.00000 
7  15/02 12.50000 
8  15/04 5.00000 

Любая помощь будет очень признательна!

+0

Да, я был просто ленив и не набирал полный df в примере –

+0

Да, в идеале у меня было бы 12 рядов на чч (если вы не можете порекомендовать лучший способ). Это соответствует другому df, который у меня есть из другого источника. –

ответ

3

Это звучит как то, что вы ищете является сводной таблицей. Мне нравится использовать reshape :: cast для этих типов таблиц. Если для данного типа расходов для данной комбинации домохозяйства/года/месяца возвращается более одного значения, это будет суммировать эти значения. Если есть только одно значение, оно возвращает значение. Аргумент «сумма» не требуется, а только предназначен для обработки исключений. Я думаю, что если ваши данные чистые, вам не нужен этот аргумент.

hh <- c("hh1", "hh1", "hh1", "hh2", "hh2", "hh2", "hh3", "hh3", "hh3") 
date <- c(sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 9)) 
value <- c(1:9) 
type <- c("income", "water", "energy", "income", "water", "energy", "income", "water", "energy") 
df <- data.frame(hh, date, value, type) 

# Load lubridate library, add date and year 
library(lubridate) 
df$month <- month(df$date) 
df$year <- year(df$date) 

# Load reshape library, run cast from reshape, creates pivot table 
library(reshape) 
dfNew <- cast(df, hh+year+month~type, value = "value", sum) 

> dfNew 
    hh year month energy income water 
1 hh1 1999  4  3  0  0 
2 hh1 1999 10  0  1  0 
3 hh1 1999 11  0  0  2 
4 hh2 1999  2  0  4  0 
5 hh2 1999  3  6  0  0 
6 hh2 1999  6  0  0  5 
7 hh3 1999  1  9  0  0 
8 hh3 1999  4  0  7  0 
9 hh3 1999  8  0  0  8 
+1

Если я правильно отношусь к сводной таблице вашей проблемы, вы можете как-то поместить ее в вопрос или пометить ее. – JMT2080AD

+0

Да, это фактически сводный стол! Спасибо за указание на это. Работал отлично, и я сделал редактирование в тегах. –

2

Попробуйте это:

df$ym<-zoo::as.yearmon(as.Date(df$date), "%y/%m") 
library(dplyr) 
df %>% group_by(ym,type) %>% 
    summarise(mean_value=mean(value)) 

Source: local data frame [9 x 3] 
Groups: ym [?] 

      ym type mean_value 
    <S3: yearmon> <fctr>  <dbl> 
1  jan 1999 income   1 
2  jun 1999 energy   3 
3  jul 1999 energy   6 
4  jul 1999 water   2 
5  ago 1999 income   4 
6  set 1999 energy   9 
7  set 1999 income   7 
8  nov 1999 water   5 
9  dez 1999 water   8 

редактирования: широкий формат:

reshape2::dcast(dfr, ym ~ type) 

     ym energy income water 
1 jan 1999  NA  1 NA 
2 jun 1999  3  NA NA 
3 jul 1999  6  NA  2 
4 ago 1999  NA  4 NA 
5 set 1999  9  7 NA 
6 nov 1999  NA  NA  5 
7 dez 1999  NA  NA  8 
0

Если я правильно понял ваше требование (из описания в этом вопросе), это то, что вы ищете:

library(dplyr) 
library(tidyr) 

df %>% mutate(date = lubridate::month(date)) %>% 
    complete(household, date = 1:12) %>% 
    spread(type, value) %>% group_by(household, date) %>% 
    mutate(Total = sum(energy, income, water, na.rm = T)) %>% 
    select(household, Month = date, energy:water, Total) 

#Source: local data frame [36 x 6] 
#Groups: household, Month [36] 
# 
# household Month energy income water Total 
#  <fctr> <dbl> <dbl> <dbl> <dbl> <dbl> 
#1 household1  1  NA  NA NA  0 
#2 household1  2  NA  NA NA  0 
#3 household1  3  NA  NA 200 200 
#4 household1  4  NA  NA NA  0 
#5 household1  5  NA  NA NA  0 
#6 household1  6  NA  NA NA  0 
#7 household1  7  NA  NA NA  0 
#8 household1  8  NA  NA NA  0 
#9 household1  9 300  NA NA 300 
#10 household1 10  NA  NA NA  0 
# ... with 26 more rows 

Примечание: Я использовал тот же df вы предоставили в вопрос. Единственное изменение, которое я сделал, это столбец value. Вместо 1:9, я использовал seq(100, 900, 100)

Если я ошибаюсь, сообщите мне, и я удалю ответ. Я добавлю объяснение того, что происходит, если это правильно.

Смежные вопросы