R: эффективный разделение-применение кадра данных (сцепление) - PullRequest
0 голосов
/ 30 апреля 2018

Я надеюсь получить совет специалиста по эффективному способу удаления строк кадра данных в одном столбце (columnA), где есть дублированное значение, и в то же время в создании новой переменной, которая объединяет записи другого столбца (columnB). ) в случаях, когда столбец A имел дубликаты. Ниже я приведу игрушечный кадр данных:

my_df <- data.frame('DateTime' = c('2017/05/05 08:30:00', '2017/05/05 08:30:00', 
                               '2017/05/05 08:30:00', '2017/12/08 08:30:00',
                              '2018/01/15 18:50:00', '2017/12/20 21:46:00',
                              '2017/11/12 18:50:00', '2017/11/03 08:30:00',
                              '2017/11/03 08:30:00', '2017/12/03 08:30:00'),
                     'Event' = c('A', 'B', 'C', 'A', 'A', 'B', 'C', 'A', 'B', 'A'),
                     'Var1' = rnorm(10),
                     stringsAsFactors = FALSE)

В этом столбце данных DateTime находится символьный столбец, и 2017/05/05 08:30:00 появляется 3 раза, а 2017/11/03 08:30:00 - дважды. Моя цель - свернуть строки, в которых есть дубликаты DateTime, и создать новый столбец, объединяющий записи Event. Таким образом, новый столбец, скажем, AllEvents, должен иметь запись A-B-C для строки 2017/05/05 08:30:00. Для строки 2017/11/03 08:30:00 в столбце DateTime значение 1009 * должно иметь значение A-B. Наконец, для всех остальных строк AllEvents должен соответствовать столбцу Event.

Моя попытка кажется очень неуклюжей.

Сначала я извлекаю уникальные значения DateTime, где имеется более одного ввода:

require(dplyr)
duped_datetime <- unique(my_df[duplicated(my_df$DateTime), 'DateTime'])

Затем я подставляю my_df для извлечения записей, в которых есть дубликаты

subset_df <- my_df[my_df$DateTime %in% duped_datetime,]

Далее я создаю функцию, которая объединяет вектор:

my_concat <- function(x){
concat_str <- subset_df %>% filter(DateTime == x) %>% 
                            select(Event) %>% 
                            unlist() %>% 
                            paste(collapse="+") 
return(concat_str)
}

Далее я перебираю повторяющиеся даты и применяю функцию my_concat:

named_vc <- sapply(duped_datetime, FUN = my_concat)

Результаты объединяются в новый фрейм данных

new_df <- data.frame('DateTime' = duped_datetime,
                     'AllEvents' = unname(named_vc), 
                      stringsAsFactors = FALSE)

Результаты объединяются, и final_df очищается для сохранения нужных мне строк и столбцов.

final_df <- left_join(my_df, new_df, by = 'DateTime')  %>% 
            mutate(AllEvents = ifelse(is.na(AllEvents), Event, AllEvents)) 
final_df <- final_df[!duplicated(final_df$DateTime),]
final_df['Event'] <- NULL  

Я получаю результат, который мне нужен, но, как вы видите, код отвратителен. Все это можно сделать в 4-х строках в Python с функциями groupby, apply и lambda, но для меня не сразу очевидно, как правильно выполнить ту же задачу в R.

    DateTime            Var1      AllEvents
2017/05/05 08:30:00   -0.8350209    A+B+C
2017/12/08 08:30:00    1.1534819    A
2018/01/15 18:50:00   -0.3501990    A
2017/12/20 21:46:00   -0.6664841    B
2017/11/12 18:50:00    1.7142981    C
2017/11/03 08:30:00   -2.0133559    A+B
2017/12/03 08:30:00   -0.6150040    A

Спасибо всем, кто имеет терпение прочитать это.

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Просто ради разнообразия, вот то же самое в data.table

library(data.table)
setDT(my_df)

my_df[, .(Var1  = first(Var1)
        , Event = paste0(Event, collapse = "+"))
      , by = DateTime]

Придает

              DateTime       Var1 Event
1: 2017/05/05 08:30:00  0.2366874 A+B+C
2: 2017/12/08 08:30:00  0.3699069     A
3: 2018/01/15 18:50:00 -0.2420663     A
4: 2017/12/20 21:46:00 -1.4720633     B
5: 2017/11/12 18:50:00 -0.5961595     C
6: 2017/11/03 08:30:00 -1.1467001   A+B
7: 2017/12/03 08:30:00 -0.6135086     A

Обратите внимание, что порядок my_df сохраняется.

0 голосов
/ 30 апреля 2018

Это можно сделать прямо в dplyr, group_by отлично работает со значениями DateTime:

my_df %>%
    group_by(DateTime) %>%
    summarise(Var1 = first(Var1),
              Event = paste0(Event, collapse = "+"))

Выход:

# A tibble: 7 x 3
  DateTime              Var1 Event
  <chr>                <dbl> <chr>
1 2017/05/05 08:30:00  0.159 A+B+C
2 2017/11/03 08:30:00 -0.610 A+B  
3 2017/11/12 18:50:00  0.465 C    
4 2017/12/03 08:30:00 -1.89  A    
5 2017/12/08 08:30:00  0.793 A    
6 2017/12/20 21:46:00  0.755 B    
7 2018/01/15 18:50:00  0.511 A  
...