Как я могу создать фрейм данных, когда у меня есть только значения для каждой ячейки (возможно, более одной строки на ячейку) и их индекс столбца и строки?

У меня есть фрейм данных, включающий значения для каждой ячейки (возможно, более одного значения), а также строки и индекса столбца.


df = data.frame(values = c(1,"Sven", 20,"Mueller","sept",2,30,"John","Mar","Hynes","Marc"), 
                colI = c(1,2,3,2,4,1,3,2,4,2,2), rowI = c(1,1,1,1,1,2,2,2,2,2,2))

И я хочу получить что-то похожее на следующий data.frame:

df_final= data.frame(Index = c(1,2), name = c("Sven, Mueller", "John, Hynes, Marc"), age = c(20,30), 
                     month = c("sept","Mar"))

Однако я не смог ничего сделать, и я также не нашел решения в Интернете. Я не могу найти решение для переноса значений в соответствующее место во фрейме данных, и я думаю, что еще более серьезной проблемой является то, что ячейки могут содержать разное количество значений.

Спасибо за вашу помощь.


person Michael Altorfer    schedule 04.08.2020    source источник
comment
Пример кода для df выдает ошибку [...] differing number of rows: 11, 10. Пожалуйста, проверьте дважды.   -  person Maurits Evers    schedule 04.08.2020
comment
Спасибо, я забыл добавить 2 в образец строки.   -  person Michael Altorfer    schedule 04.08.2020


Ответы (3)


Используя базу R, вы можете сначала aggregate ваши данные в одну строку, разделенную запятыми, для каждой строки и индекса столбца, а затем использовать unstack.

temp <- aggregate(values~colI + rowI, df, toString)
unstack(temp, values~colI)

#  X1                X2 X3   X4
#1  1     Sven, Mueller 20 sept
#2  2 John, Hynes, Marc 30  Mar

данные

df <- structure(list(values = c("1", "Sven", "20", "Mueller", "sept", 
"2", "30", "John", "Mar", "Hynes", "Marc"), colI = c(1, 2, 3, 
2, 4, 1, 3, 2, 4, 2, 2), rowI = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 
2, 2)), class = "data.frame", row.names = c(NA, -11L))
person Ronak Shah    schedule 04.08.2020
comment
Это намного проще, чем мое решение. - person Martin Gal; 04.08.2020

Вы можете использовать dplyr, tidyr и stringr, все они включены в tidyverse:

df %>%
# bring your data into a wider format
  pivot_wider(id_cols=rowI, names_from=colI, values_from=values, values_fn=list) %>% 
# remove the nested listing
  unnest(everything()) %>%
# rename the columns
  select(Index = rowI, name=`2`, age=`3`, month=`4`) %>%
# group all rows based on the index
  group_by(Index) %>%
# concatenate the name column
  mutate(name=str_c(name, collapse=", ")) %>%
# remove duplicates
  distinct()

возвращается

# A tibble: 2 x 4
# Groups:   Index [2]
  Index name              age   month
  <dbl> <chr>             <chr> <chr>
1     1 Sven, Mueller     20    sept 
2     2 John, Hynes, Marc 30    Mar 

Примечание. Я немного изменил ваши входные данные и добавил один 2 в столбец rowI (см. Комментарий Маурица Эверса).

person Martin Gal    schedule 04.08.2020
comment
Спасибо Ронаку и Мартину за вашу помощь. Простое решение отлично решает мой вопрос. - person Michael Altorfer; 04.08.2020

Другое решение

df %>% 
  pivot_wider(rowI, names_from = colI, values_from = values, values_fn = toString) %>% 
  select(-rowI) %>% 
  purrr::set_names(c("ID", "name", "age", "month"))
person Yuriy Saraykin    schedule 04.08.2020