#r #dataframe #grouping
#r #фрейм данных #группировка
Вопрос:
У меня есть фрейм данных, описывающий уровни владения компаний, который выглядит следующим образом:
Company Subsidiary1 Subsidiary2 Subsidiary3
DE5930 DE5931 NA NA
GB3489 GB3490 NA NA
GB3489 GB3490 GB3491 NA
US2036 US2037 NA NA
US2036 US2037 US2038 NA
US2036 US2037 US2038 GB3491
....# and so on
Теперь я хотел бы создать один столбец всех дочерних компаний для каждой компании, который должен выглядеть следующим образом:
Company Subsidiaries
DE5930 DE5931
GB3489 GB3490
GB3489 GB3491
US2036 US2037
US2036 US2038
US2036 GB3491
Набор данных действительно большой (более 100 000 строк), и я не смог найти никаких решений с использованием функции group_by
or aggregate
, поскольку большинство примеров относятся к числовым переменным (например, average).
Одной из идей было бы удалить дубликаты с помощью df[ !duplicated(df$Subsidiary1), ]
, чтобы сохранить первое появление каждого дочернего предприятия, а затем сдвинуть значения влево, но проблема в том, что одно дочернее предприятие может принадлежать нескольким компаниям (например, «GB3491»), и я не хочу терять эти наблюдения. Есть ли какое-либо элегантное решение этой проблемы?
Заранее благодарю вас!
Ответ №1:
Я бы предложил следующий tidyverse
подход:
library(tidyverse)
#Data
df <- structure(list(Company = c("DE5930", "GB3489", "GB3489", "US2036",
"US2036", "US2036"), Subsidiary1 = c("DE5931", "GB3490", "GB3490",
"US2037", "US2037", "US2037"), Subsidiary2 = c(NA, NA, "GB3491",
NA, "US2038", "US2038"), Subsidiary3 = c(NA, NA, NA, NA, NA,
"GB3491")), class = "data.frame", row.names = c(NA, -6L))
Код:
df %>% pivot_longer(cols = -Company) %>% select(-name) %>%
filter(!is.na(value)) %>%
filter(!duplicated(paste(Company,value)))
Вывод:
# A tibble: 6 x 2
Company value
<chr> <chr>
1 DE5930 DE5931
2 GB3489 GB3490
3 GB3489 GB3491
4 US2036 US2037
5 US2036 US2038
6 US2036 GB3491
Ответ №2:
Мы можем использовать coalesce
library(dplyr)
df1 %>%
transmute(Company, Subsidiaries =
coalesce(!!! rlang::syms(rev(names(df1)[-1]))))
# Company Subsidiaries
#1 DE5930 DE5931
#2 GB3489 GB3490
#3 GB3489 GB3491
#4 US2036 US2037
#5 US2036 US2038
#6 US2036 GB3491
Или с base R
помощью max.col
cbind(df1[1], Subsidiaries = df1[-1][cbind(seq_len(nrow(df1)),
max.col(!is.na(df1[-1]), "last"))])
данные
df1 <- structure(list(Company = c("DE5930", "GB3489", "GB3489", "US2036",
"US2036", "US2036"), Subsidiary1 = c("DE5931", "GB3490", "GB3490",
"US2037", "US2037", "US2037"), Subsidiary2 = c(NA, NA, "GB3491",
NA, "US2038", "US2038"), Subsidiary3 = c(NA, NA, NA, NA, NA,
"GB3491")), class = "data.frame", row.names = c(NA, -6L))