Объединение нескольких строк в один ряд

У меня есть некоторые проблемы с моим фреймом данных в R. Мой фрейм данных выглядит примерно так:

ID  TIME    DAY        URL_NAME      VALUE  TIME_SPEND
1    12:15  Monday      HOME         4        30
1    13:15  Tuesday     CUSTOMERS    5        21  
1    15:00  Thursday    PLANTS       8        8    
1    16:21  Friday      MANAGEMENT   1        6
....

Итак, я хочу записать строки, содержащие один и тот же "идентификатор" в одну строку. Выглядит примерно так:

ID  TIME    DAY         URL_NAME     VALUE    TIME_SPEND  TIME1  DAY1        URL_NAME1      VALUE1  TIME_SPEND1  TIME2    DAY2        URL_NAME2      VALUE2  TIME_SPEND2  TIME3    DAY3        URL_NAME3      VALUE3  TIME_SPEND3
1    12:15  Monday      HOME         4        30          13:15  Tuesday     CUSTOMERS      5       21           15:00    Thursday    PLANTS         8       8            16:21    Friday      MANAGEMENT     1       6

Моя вторая проблема заключается в том, что существует около 150000 уникальных идентификаторов, и я хотел бы сделать это для всего фрейма данных.

Я не нашел решения, подходящего для моей проблемы. Я был бы рад любым решениям или ссылкам для решения моей проблемы.

1 ответ

Я бы порекомендовал использовать dcast из пакета "data.table", который позволит вам изменять формы нескольких переменных показателей одновременно.

Пример:

library(data.table)
as.data.table(mydf)[, dcast(.SD, ID ~ rowid(ID), value.var = names(mydf)[-1])]
#    ID TIME_1 TIME_2 TIME_3   DAY_1   DAY_2    DAY_3 URL_NAME_1 URL_NAME_2 URL_NAME_3 VALUE_1 VALUE_2
# 1:  1  12:15  13:15  15:00  Monday Tuesday Thursday       HOME  CUSTOMERS     PLANTS       4       5
# 2:  2  14:15  10:19     NA Tuesday  Monday       NA  CUSTOMERS  CUSTOMERS         NA       2       9
#    VALUE_3 TIME_SPEND_1 TIME_SPEND_2 TIME_SPEND_3
# 1:       8           30           19           40
# 2:      NA           21            8           NA

Вот пример используемых данных:

mydf <- data.frame(
  ID = c(1, 1, 1, 2, 2),
  TIME = c("12:15", "13:15", "15:00", "14:15", "10:19"),
  DAY = c("Monday", "Tuesday", "Thursday", "Tuesday", "Monday"),
  URL_NAME = c("HOME", "CUSTOMERS", "PLANTS", "CUSTOMERS", "CUSTOMERS"),
  VALUE = c(4, 5, 8, 2, 9),
  TIME_SPEND = c(30, 19, 40, 21, 8)
)
mydf
#   ID  TIME      DAY  URL_NAME VALUE TIME_SPEND
# 1  1 12:15   Monday      HOME     4         30
# 2  1 13:15  Tuesday CUSTOMERS     5         19
# 3  1 15:00 Thursday    PLANTS     8         40
# 4  2 14:15  Tuesday CUSTOMERS     2         21
# 5  2 10:19   Monday CUSTOMERS     9          8

Попробуй это tidyverseрешение, которое даст результат, близкий к тому, что вы хотите. Вы можете сгруппировать по TIMEзатем создайте последовательный идентификатор, который будет определять будущие столбцы. После этого измените форму на длинную (pivot_longer()), объедините имя переменной с идентификатором, а затем измените форму на широкую (pivot_wider()). Вот код, в котором я использовал собственный набор данных,

       df1 <- data.frame(Components = c(rep("ABC",5),rep("BCD",5)), 
              Size = c(sample(1:100,5),sample(45:100,5)),
              Age = c(sample(1:100,5),sample(45:100,5)))

Для созданного выше набора данных решением является следующий фрагмент кода:

       library(tidyverse)
#Code
newdf <- df1 %>% group_by(Components) %>% mutate(id=row_number()) %>%
  pivot_longer(-c(Components,id)) %>%
  mutate(name=paste0(name,'.',id)) %>% select(-id) %>%
  pivot_wider(names_from = name,values_from=value)

ВЫХОД будет выглядеть так:

       # A tibble: 2 x 11
# Groups:   Components [2]
  Components Size.1 Age.1 Size.2 Age.2 Size.3 Age.3 Size.4 Age.4 Size.5 Age.5
  <fct>       <int> <int>  <int> <int>  <int> <int>  <int> <int>  <int> <int>
1 ABC            23    94     52    89     15    25     76    38     33    99
2 BCD            59    62     55    81     81    61     80    83     97    68

АЛЬТЕРНАТИВНОЕ РЕШЕНИЕ:

Мы могли бы использовать unite чтобы объединить столбцы, а затем используйте pivot_wider

       library(dplyr)
library(tidyr)
library(data.table)
df1 %>%
   mutate(rn = rowid(Components)) %>%
   pivot_longer(cols = Size:Age) %>% 
   unite(name, name, rn, sep=".") %>%
   pivot_wider(names_from = name, values_from = value)

ВЫХОД будет выглядеть так:

       # A tibble: 2 x 11
#  Components Size.1 Age.1 Size.2 Age.2 Size.3 Age.3 Size.4 Age.4 Size.5 Age.5
#  <chr>       <int> <int>  <int> <int>  <int> <int>  <int> <int>  <int> <int>
#1 ABC            11    16     79    57     70     2     80     6     91    24
#2 BCD            67    81     63    77     48    73     52   100     49    76

Оба решения - akrun детище @ Duck's Duck и @ akrun. Спасибо им огромное.

Другие вопросы по тегам