Слияние и частичное добавление строк без групп в R - PullRequest
0 голосов
/ 09 октября 2018

Ниже приводится описание моей проблемы, написанной для dplyr:

library(tidyverse)

df <- tibble(State = c("A", "A", "A", "A", "A", "A", "B", "B", "B"),
             District_code = c(1:9),
                 District = c("North", "West", "North West", "South", "East", "South East", 
                              "XYZ", "ZYX", "AGS"), 
                 Population = c(1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 
                                7000000, 8000000, 9000000))

df
#> # A tibble: 9 x 4
#>   State District_code District   Population
#>   <chr>         <int> <chr>           <dbl>
#> 1 A                 1 North         1000000
#> 2 A                 2 West          2000000
#> 3 A                 3 North West    3000000
#> 4 A                 4 South         4000000
#> 5 A                 5 East          5000000
#> 6 A                 6 South East    6000000
#> 7 B                 7 XYZ           7000000
#> 8 B                 8 ZYX           8000000
#> 9 B                 9 AGS           9000000

В некоторых штатах мне необходимо объединить округа, используя названия, в меньшее количество географических категорий.В частности, государство А должно иметь только: «Северо-Запад - Северо-Запад» и «Юго-Восток - Юго-Восток».Необходимо добавить некоторые переменные, такие как Population;но другие, такие как District_code, должны получить NA.Я нашел этот пример операций над строками, но это не совсем то же самое. Группировка , похоже, не применяется.

Конечный результат должен выглядеть примерно так:

new_df
#> # A tibble: 5 x 4
#>   State District_code District                  Population
#>   <chr>         <int> <chr>                          <dbl>
#> 1 A                NA North - West - North West    5000000
#> 2 A                NA South - East - South East   15000000
#> 3 B                 7 XYZ                          7000000
#> 4 B                 8 ZYX                          8000000
#> 5 B                 9 AGS                          9000000

В реальном кадре данных существует ряд переменных, таких как Populationэто необходимо добавить, а также ряд других переменных, таких как District_code, которые должны будут получать значения NA.

Спасибо огромное за любую помощь!

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

В некоторых штатах мне нужно объединить округа, используя названия, в меньшее количество географических категорий.В частности, государство А должно иметь только: «Северо-Запад - Северо-Запад» и «Юго-Восток - Юго-Восток».

Вам нужно будет записать правила группировки, например ...

merge_rules = list(
  list(State = "A", District = c("North", "West", "North West")),
  list(State = "A", District = c("South", "East", "South East"))
)

Необходимо добавить некоторые переменные, такие как Population;но другие, такие как District_code, должны получить NA.

Я бы сделал это, поместив правила слияния в таблицу;выполнение расчетов после слияния;и перебирая неродные ряды.Вот способ data.table ...

library(data.table)
DT  = data.table(df)
mDT = rbindlist(lapply(merge_rules, as.data.table), id = "g")

gDT = DT[mDT, on=.(State, District)][, .(
  District_code = District_code[NA_integer_],
  District = paste(District, collapse = " - "),
  Population = sum(Population)
), by=.(g, State)]

rbind(
  DT[!mDT, on=.(State, District)],
  gDT[, !"g"]
)[order(State, District)]

   State District_code                  District Population
1:     A            NA North - West - North West    6.0e+06
2:     A            NA South - East - South East    1.5e+07
3:     B             9                       AGS    9.0e+06
4:     B             7                       XYZ    7.0e+06
5:     B             8                       ZYX    8.0e+06

И, я полагаю, обратный путь похож:

mtib = bind_rows(lapply(merge_rules, as.tibble), .id = "g")

gtib = right_join(df, mtib, by=c("State", "District")) %>% 
  group_by(g, State) %>% summarise(
    District_code = District_code[NA_integer_],
    District = paste(District, collapse = " - "),
    Population = sum(Population)    
  )

bind_rows(
  anti_join(df, mtib, by=c("State", "District")),
  gtib %>% ungroup %>% select(-g)
) %>% arrange(State, District)

# A tibble: 5 x 4
  State District_code District                  Population
  <chr>         <int> <chr>                          <dbl>
1 A                NA North - West - North West    6000000
2 A                NA South - East - South East   15000000
3 B                 9 AGS                          9000000
4 B                 7 XYZ                          7000000
5 B                 8 ZYX                          8000000
0 голосов
/ 09 октября 2018

Вот один из способов получить агрегированные данные по населению для государства A:

df %>% 
  filter(State == "A") %>%
  mutate(`North - West - North West` = (District == "North"|District == "West"|District == "North West"), 
         `South - East - South East` = (District == "South"|District == "East"|District == "South East")) %>% 
  gather(key = Districts, value = present, 5:6) %>% 
  filter(present != FALSE) %>% 
  group_by(Districts) %>% 
  summarise(Population = sum(Population))

, который дает вывод:

  Districts          Population
  <chr>                   <dbl>
1 North - West - No…    6000000
2 South - East - So…   15000000

Кто-то должен помочь нам поместить вышеперечисленное воригинал df.

0 голосов
/ 09 октября 2018

Вы можете использовать fct_collapse, чтобы указать новые уровни факторов, а затем использовать summarise в новых группах.

df %>%
  mutate(District = 
           fct_collapse(District, 
                        "North - West - North West" = c("North", "West", "North West"), 
                        "South - East - South East" = c("South", "East", "South East"))) %>% 
  group_by(State, District) %>% 
  summarise(Population = sum(Population), 
            District_code = ifelse(n() > 1, NA_real_, District_code))

# A tibble: 5 x 3
# Groups:   State [?]
#   State District                  Population
#   <chr> <fct>                          <dbl>
# 1 A     South - East - South East   15000000
# 2 A     North - West - North West    6000000
# 3 B     AGS                          9000000
# 4 B     XYZ                          7000000
# 5 B     ZYX                          8000000

Если вы хотите изменить район только для какого-то определенного штата, вы можете добавить case_when или if_else, как это, а также обусловить функцию суммирования для типа столбца (здесь двойнойдля населения в отличие от целого числа для округа)

df %>%
  mutate(District = 
           case_when(State == "A" ~ 
                       fct_collapse(District, 
                                    "North - West - North West" = c("North", "West", "North West"), 
                                    "South - East - South East" = c("South", "East", "South East")), 
                     TRUE ~ factor(District))) %>% 
  group_by(State, District) %>% 
  summarise_all(funs({if(is.double(.)) {
    sum(.) 
  } else {
    if (length(unique(.)) > 1) {
      NA
    } else {
      unique(.)
    }
  }}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...