R: условен агрегат, базиран на факторно ниво и година

Имам набор от данни в R, който се опитвам да обобщя по ниво на колона и година, което изглежда така:

    City  State   Year   Status      Year_repealed   PolicyNo
    Pitt   PA     2001   InForce                        6
    Phil.  PA     2001   Repealed        2004           9
    Pitt   PA     2002   InForce                        7
    Pitt   PA     2005   InForce                        2

Това, което бих искал да създам, е мястото, където за всяка година обобщавам PolicyNo в щатите, като вземам предвид датата, на която политиката е била отменена. Резултатите, които тогава бих получил са:

    Year    State PolicyNo
    2001     PA     15  
    2002     PA     22
    2003     PA     22
    2004     PA     12 
    2005     PA     14

Не съм сигурен как да направя разделянето и агрегирането на данните в зависимост от данните за отмяна и се чудех дали има начин да се постигне лесно това е R.


person Tobi Adekanye    schedule 03.12.2016    source източник


Отговори (2)


Може да ви помогне да разделите това на два различни проблема.

  1. Вземете таблица, която показва промяната в PolicyNo за всеки град-щат-година.
  2. Обобщете тази таблица, за да покажете номера на политиката във всяка държавна година.

За да постигнем (1), добавяме липсващите години с NA PolicyNo и добавяме отмените като отрицателни PolicyNo наблюдения.

library(dplyr)

df = structure(list(City = c("Pitt", "Phil.", "Pitt", "Pitt"), State = c("PA", "PA", "PA", "PA"), Year = c(2001L, 2001L, 2002L, 2005L), Status = c("InForce", "Repealed", "InForce", "InForce"), Year_repealed = c(NA, 2004L, NA, NA), PolicyNo = c(6L, 9L, 7L, 2L)), .Names = c("City", "State", "Year", "Status", "Year_repealed", "PolicyNo"), class = "data.frame", row.names = c(NA, -4L))

repeals = df %>%
  filter(!is.na(Year_repealed)) %>%
  mutate(Year = Year_repealed, PolicyNo = -1 * PolicyNo)
repeals
#    City State Year   Status Year_repealed PolicyNo
# 1 Phil.    PA 2004 Repealed          2004       -9

all_years = expand.grid(City = unique(df$City), State = unique(df$State),
                        Year = 2001:2005)

df = bind_rows(df, repeals, all_years)
#     City State Year   Status Year_repealed PolicyNo
# 1   Pitt    PA 2001  InForce            NA        6
# 2  Phil.    PA 2001 Repealed          2004        9
# 3   Pitt    PA 2002  InForce            NA        7
# 4   Pitt    PA 2005  InForce            NA        2
# 5  Phil.    PA 2004 Repealed          2004       -9
# 6   Pitt    PA 2001     <NA>            NA       NA
# 7  Phil.    PA 2001     <NA>            NA       NA
# 8   Pitt    PA 2002     <NA>            NA       NA
# 9  Phil.    PA 2002     <NA>            NA       NA
# 10  Pitt    PA 2003     <NA>            NA       NA
# 11 Phil.    PA 2003     <NA>            NA       NA
# 12  Pitt    PA 2004     <NA>            NA       NA
# 13 Phil.    PA 2004     <NA>            NA       NA
# 14  Pitt    PA 2005     <NA>            NA       NA
# 15 Phil.    PA 2005     <NA>            NA       NA

Сега таблицата показва всеки град-държава-година и включва отмяна. Това е таблица, която можем да обобщим.

df = df %>%
  group_by(Year, State) %>%
  summarize(annual_change = sum(PolicyNo, na.rm = TRUE))
df
# Source: local data frame [5 x 3]
# Groups: Year [?]
# 
#    Year State annual_change
#   <int> <chr>         <dbl>
# 1  2001    PA            15
# 2  2002    PA             7
# 3  2003    PA             0
# 4  2004    PA            -9
# 5  2005    PA             2

Това ни позволява да нямаме промяна в политиката във всяка щатска година. Кумулативната сума върху промените ни дава нива.

df = df %>%
  ungroup() %>%
  mutate(PolicyNo = cumsum(annual_change))
df
# # A tibble: 5 × 4
#    Year State annual_change PolicyNo
#   <int> <chr>         <dbl>    <dbl>
# 1  2001    PA            15       15
# 2  2002    PA             7       22
# 3  2003    PA             0       22
# 4  2004    PA            -9       13
# 5  2005    PA             2       15
person effel    schedule 03.12.2016
comment
Още един въпрос @effel, ако нямаш нищо против. В случай, че имам няколко колони с политика не, има ли начин да извърша този анализ наведнъж? - person Tobi Adekanye; 04.12.2016
comment
Да, бих предложил да стопим по-широката таблица и да добавим променливата колона (указваща политики) към извикванията group_by като още един идентификатор. Ако горното работи добре, не се колебайте да приемете отговора. - person effel; 04.12.2016

С пакета data.table можете да го направите по следния начин:

melt(setDT(dat), 
     measure.vars = c(3,5),
     value.name = 'Year',
     value.factor = FALSE)[!is.na(Year)
                           ][variable == 'Year_repealed', PolicyNo := -1*PolicyNo
                             ][CJ(Year = min(Year):max(Year), State = State, unique = TRUE), on = .(Year, State)
                               ][is.na(PolicyNo), PolicyNo := 0
                                 ][, .(PolicyNo = sum(PolicyNo)), by = .(Year, State)
                                   ][, .(Year, State, PolicyNo = cumsum(PolicyNo))]

Резултатът от горния код:

   Year State PolicyNo
1: 2001    PA       15
2: 2002    PA       22
3: 2003    PA       22
4: 2004    PA       13
5: 2005    PA       15

Както можете да видите, има няколко стъпки, необходими за постигане на желания краен резултат:

  • Първо конвертирате в data.table (setDT(dat)) и преоформяте това в дълъг формат и премахвате редовете без Year
  • След това правите стойността за редовете, които имат 'Year_repealed', на отрицателна.
  • С кръстосано свързване (CJ) се уверявате, че всички години за всяко състояние са налице и преобразувате NA-стойностите в колоната PolicyNo в нула.
  • Накрая обобщавате по години и правите кумулативна сума за резултата.
person h3rm4n    schedule 03.12.2016