Расширьте Tibble рядом - PullRequest
       3

Расширьте Tibble рядом

1 голос
/ 17 октября 2019

Мой вопрос заключается в следующем: с помощью mutate я могу создавать новые столбцы, например, в виде комбинации существующих, но что если мне нужно создать новые строки в качестве комбинации существующих? Например, рассмотрим

df<-structure(list(year = c(2013L, 2014L, 2015L, 2016L, 2017L, 2013L, 
2014L, 2015L, 2016L, 2017L), reporter = c("EU28", "EU28", "EU28", 
"EU28", "EU28", "UK", "UK", "UK", "UK", "UK"), partner = c("ACP", 
"ACP", "ACP", "ACP", "ACP", "ACP", "ACP", "ACP", "ACP", "ACP"
), nace = c("FDI", "FDI", "FDI", "FDI", "FDI", "FDI", "FDI", 
"FDI", "FDI", "FDI"), inward_stock = c(85483.9, 108674.6, 98536.9, 
114328.5, 174077.2, 4733.1, 5229.2, 5892.5, 7542.7, 20759), outward_stock = c(189229.3, 
223497.6, 325336.3, 301348.9, 304675.4, 38683, 46732.6, 49357.3, 
46985.6, 39748.4)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-10L))

Я хотел бы добавить новые строки для 2013-2017 годов, где есть новый репортер EU27, а значения внутренних и внешних запасов - это значения EU28 без учетаВзнос Великобритании.

Например, в 2013 году inward_stock для EU27 будет 85484- 4733 = 80751 и outward_stock 189229.-38683 = 150546.

Кто-нибудь знает, как этого добиться безпереживает громоздкие повороты / разворачивания? Я хотел бы добавить 5 новых строк в общей сложности

Спасибо!

Ответы [ 4 ]

2 голосов
/ 17 октября 2019

Я думаю, что в этом случае было бы вполне естественно использовать summarize() для создания данных для EU27, а затем связать это с исходными данными:

library(tidyverse)

eu27 <- df %>%
  group_by_at(vars(-reporter, -ends_with("stock"))) %>%
  summarize_at(vars(inward_stock, outward_stock), ~ {
    .x[reporter == "EU28"] - .x[reporter == "UK"]
  }) %>% mutate(reporter = "EU27")

bind_rows(df, eu27)
#> # A tibble: 15 x 6
#>     year reporter partner nace  inward_stock outward_stock
#>    <int> <chr>    <chr>   <chr>        <dbl>         <dbl>
#>  1  2013 EU28     ACP     FDI         85484.       189229.
#>  2  2014 EU28     ACP     FDI        108675.       223498.
#>  3  2015 EU28     ACP     FDI         98537.       325336.
#>  4  2016 EU28     ACP     FDI        114328.       301349.
#>  5  2017 EU28     ACP     FDI        174077.       304675.
#>  6  2013 UK       ACP     FDI          4733.        38683 
#>  7  2014 UK       ACP     FDI          5229.        46733.
#>  8  2015 UK       ACP     FDI          5892.        49357.
#>  9  2016 UK       ACP     FDI          7543.        46986.
#> 10  2017 UK       ACP     FDI         20759         39748.
#> 11  2013 EU27     ACP     FDI         80751.       150546.
#> 12  2014 EU27     ACP     FDI        103445.       176765 
#> 13  2015 EU27     ACP     FDI         92644.       275979 
#> 14  2016 EU27     ACP     FDI        106786.       254363.
#> 15  2017 EU27     ACP     FDI        153318.       264927

Вот также версия с громоздкойповорот, используя новые функции pivot_* в Tidyr:

df %>%
  pivot_longer(cols = ends_with("stock"), names_to = "variable") %>%
  pivot_wider(names_from = reporter) %>%
  mutate(EU27 = EU28 - UK) %>%
  pivot_longer(cols = c(EU28, UK, EU27), names_to = "reporter") %>%
  pivot_wider(names_from = variable)
#> # A tibble: 15 x 6
#>     year partner nace  reporter inward_stock outward_stock
#>    <int> <chr>   <chr> <chr>           <dbl>         <dbl>
#>  1  2013 ACP     FDI   EU28           85484.       189229.
#>  2  2013 ACP     FDI   UK              4733.        38683 
#>  3  2013 ACP     FDI   EU27           80751.       150546.
#>  4  2014 ACP     FDI   EU28          108675.       223498.
#>  5  2014 ACP     FDI   UK              5229.        46733.
#>  6  2014 ACP     FDI   EU27          103445.       176765 
#>  7  2015 ACP     FDI   EU28           98537.       325336.
#>  8  2015 ACP     FDI   UK              5892.        49357.
#>  9  2015 ACP     FDI   EU27           92644.       275979 
#> 10  2016 ACP     FDI   EU28          114328.       301349.
#> 11  2016 ACP     FDI   UK              7543.        46986.
#> 12  2016 ACP     FDI   EU27          106786.       254363.
#> 13  2017 ACP     FDI   EU28          174077.       304675.
#> 14  2017 ACP     FDI   UK             20759         39748.
#> 15  2017 ACP     FDI   EU27          153318.       264927

Я думаю, что выше показывает интересную модель, которая может быть полезна. Одна поворотная функция, которая может выполнять как «более длинные», так и «более широкие» шаги за один вызов, что-то вроде этого:

df %>%
  pivot(ends_with("stock"), names_to = "variable", names_from = reporter) %>%
  mutate(EU27 = EU28 - UK) %>%
  pivot(c(EU28, UK, EU27), names_to = "reporter", names_from = variable)

Создано в 2019-10-17 с помощью Представить пакет (v0.3.0)

0 голосов
/ 17 октября 2019

Используя пакет data.table, мы можем решить проблему следующим образом

library(data.table)
setorder(setDT(df), year, -reporter)
df[, .(reporter = "EU27", partner = "ACP", nace = "FDI", inward_stock = diff(inward_stock), outward_stock = diff(outward_stock)), year] %>% 
  rbind(df)

Другая альтернатива

library(data.table)
setDT(df)
df[, -"reporter"][, c(.(reporter = "EU27"), lapply(.SD, function(x) if(is.numeric(x)) -diff(x) else unique(x))), year] %>% 
  rbind(df)
0 голосов
/ 17 октября 2019

У меня есть это решение, используя gather и spread из dplyr:

df %>%
gather(type, stock, -c(year, reporter, partner, nace)) %>%
spread(reporter, stock) %>%
mutate(EU27=EU28-UK) %>%
gather(reporter, stock, -c(year, partner, nace, type)) %>%
spread(type, stock)

Вывод:

# A tibble: 15 x 6
    year partner nace  reporter inward_stock outward_stock
   <int> <chr>   <chr> <chr>           <dbl>         <dbl>
 1  2013 ACP     FDI   EU27           80751.       150546.
 2  2013 ACP     FDI   EU28           85484.       189229.
 3  2013 ACP     FDI   UK              4733.        38683 
 4  2014 ACP     FDI   EU27          103445.       176765 
 5  2014 ACP     FDI   EU28          108675.       223498.
 6  2014 ACP     FDI   UK              5229.        46733.
 7  2015 ACP     FDI   EU27           92644.       275979 
 8  2015 ACP     FDI   EU28           98537.       325336.
 9  2015 ACP     FDI   UK              5892.        49357.
10  2016 ACP     FDI   EU27          106786.       254363.
11  2016 ACP     FDI   EU28          114328.       301349.
12  2016 ACP     FDI   UK              7543.        46986.
13  2017 ACP     FDI   EU27          153318.       264927 
14  2017 ACP     FDI   EU28          174077.       304675.
15  2017 ACP     FDI   UK             20759         39748.
0 голосов
/ 17 октября 2019

Я не уверен, насколько динамично вы хотите, чтобы это происходило без поворота, но решение, которое соответствует вашему примеру, может быть,

new_reporter <- 'EU27'
l1 <- split(df, df$reporter)

rbind(df, data.frame(year = l1[[1]][1], 
                     reporter = new_reporter, 
                     partner = l1[[1]]$partner, 
                     nace = l1[[1]]$nace, 
                    l1[[1]][c(5:6)] - l1[[2]][c(5:6)]))

# A tibble: 15 x 6
#    year reporter partner nace  inward_stock outward_stock
#   <int> <chr>    <chr>   <chr>        <dbl>         <dbl>
# 1  2013 EU28     ACP     FDI         85484.       189229.
# 2  2014 EU28     ACP     FDI        108675.       223498.
# 3  2015 EU28     ACP     FDI         98537.       325336.
# 4  2016 EU28     ACP     FDI        114328.       301349.
# 5  2017 EU28     ACP     FDI        174077.       304675.
# 6  2013 UK       ACP     FDI          4733.        38683 
# 7  2014 UK       ACP     FDI          5229.        46733.
# 8  2015 UK       ACP     FDI          5892.        49357.
# 9  2016 UK       ACP     FDI          7543.        46986.
#10  2017 UK       ACP     FDI         20759         39748.
#11  2013 EU27     ACP     FDI         80751.       150546.
#12  2014 EU27     ACP     FDI        103445.       176765 
#13  2015 EU27     ACP     FDI         92644.       275979 
#14  2016 EU27     ACP     FDI        106786.       254363.
#15  2017 EU27     ACP     FDI        153318.       264927 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...