Суммировать два кадра данных частично - PullRequest
0 голосов
/ 30 января 2019

У меня есть два кадра данных.Для некоторых строк df1 есть подходящая строка в df2.Теперь необходимо манипулировать некоторыми столбцами df1, чтобы они содержали сумму своего собственного значения и эквивалентное значение из df2.

В следующем примере столбцы 'count1' и 'count2' должны быть суммированы,но не столбец 'type'.

df1 <- data.frame(id = c("one_a", "two_a", "three_a", "four_a"), type = c(8,7,6,5), count1 = c(1,2,1,NA), count2 = c(NA,0,1,0), id_df2 = c("one", "two", "three", "four"))
df2 <- data.frame(id = c("one", "two", "four"), type = c(8,7,5), count1 = c(0,1,1), count2 = c(0,0,1))
result <- data.frame(id = c("one_a", "two_a", "three_a", "four_a"), type = c(8,7,6,5), count1 = c(1,3,1,1), count2 = c(0,0,1,1))

> df1
       id type count1 count2 id_df2
1   one_a    8      1     NA     one
2   two_a    7      2      0     two
3 three_a    6      1      1   three
4  four_a    5     NA      0    four

> df2
    id type count1 count2
1  one    8      0      0
2  two    7      1      0
3 four    5      1      1

> result
       id type count1 count2
1   one_a    8      1      0
2   two_a    7      3      0
3 three_a    6      1      1
4  four_a    5      1      1

Были похожие вопросы, и я попытался найти решение, разделив кадры данных и объединив их впоследствии.Мне просто интересно, есть ли более элегантный способ сделать это.В моем исходном наборе данных около 300 столбцов, поэтому я ищу решение, которое можно масштабировать.

Заранее спасибо chuckmorris

Ответы [ 2 ]

0 голосов
/ 30 января 2019

немного менее элегантно, но, тем не менее, работает:

result_2 <- df2 %>% 
  mutate(id = paste0(id, "_a")) %>%
  bind_rows(df1) %>% 
  select(-id_df2) %>% 
  replace(., is.na(.), 0) %>%
  group_by(id) %>% 
  summarise(count1 = sum(count1), count2 = sum(count2), type = max(type)) %>% 
  mutate(id_df2 = as.factor(id)) %>% 
  select(c(id_df2, type, count1, count2), -id)
0 голосов
/ 30 января 2019

Вы можете сделать:

library(dplyr)

df1 %>% select(-id_df2) %>%
  bind_rows(df2) %>%
  mutate(id = gsub("_.*", "", id)) %>%
  replace(., is.na(.), 0) %>%
  group_by(id, type) %>%
  summarise_at(vars(contains("count")), funs(sum))

Где вывод:

# A tibble: 4 x 4
# Groups:   id [?]
  id     type count1 count2
  <chr> <dbl>  <dbl>  <dbl>
1 four      5      1      1
2 one       8      1      0
3 three     6      1      1
4 two       7      3      0

Но также:

df1 %>% select(-id_df2) %>%
  bind_rows(df2) %>%
  mutate(id = ifelse(grepl("_", id), id, paste0(id, "_a"))) %>%
  replace(., is.na(.), 0) %>%
  group_by(id, type) %>%
  summarise_at(vars(contains("count")), funs(sum))

Если вы заинтересованы в сохранении_a part.

Другой подход был бы с объединением, преобразованием в long и последующим распространением назад, например:

library(tidyverse)

df1 %>% 
  left_join(df2, by = c("id_df2" = "id")) %>%
  gather(var, val, -id) %>%
  mutate(var = gsub("\\..*", "", var)) %>%
  distinct(id, var, val) %>%
  filter(!var == "id_df2") %>%
  group_by(id, var) %>%
  summarise(val = sum(as.numeric(val), na.rm = T)) %>%
  spread(var, val) 

Предоставление:

# A tibble: 4 x 4
# Groups:   id [4]
  id      count1 count2  type
  <fct>    <dbl>  <dbl> <dbl>
1 four_a       1      1     5
2 one_a        1      0     8
3 three_a      1      1     6
4 two_a        3      0     7

Это может представлять интерес, если окончание _a имеет специальное назначение, например, есть группы с _b, _c и т. Д. (В этом случае вышеприведенный метод потерпит неудачу).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...