2016-10-12 2 views
0

Я застрял в задаче о проблемах с данными. Каждый набор данных имеет несколько значений aValue за одно значение aName. Это можно легко представить в аккуратном кадре данных.Распределение ключей значений в столбцах

someDatasets <- list(dataset1 = data.frame(aName = c("a", "a", "a", "b", "b"), aValue = 1:5, dataset = "ds1"), 
        dataset2 = data.frame(aName = c("a", "a", "a", "b", "c", "c"), aValue = (1:6)*10 , dataset = "ds2"), 
        dataset3 = data.frame(aName = c("a", "c", "c", "c"), aValue = (1:4)*100, dataset = "ds3")) 

tidyData <- Reduce(dplyr::bind_rows, someDatasets) 

Я хотел бы «разложить» переменную набора данных в отдельные столбцы. (Я не был в состоянии использовать tidyr::spread для создания желаемого выхода из-за дублирование ключей.)

### 
# Desired output 
### 
# aName ds1 ds2 ds3 
# a  1 10 100 
# a  2 20 NA 
# a  3 30 NA 
# b  4 40 NA 
# b  5 NA NA 
# c  NA 50 200 
# c  NA 60 300 
# c  NA NA 400 

Есть аккуратный способ получения желаемых результатов?

пс: Я знаю spread-key-value-pairs-when-keys-are-in-different-columns вопрос, но решение

dcast(melt(someDatasets, id = "aName", na.rm = TRUE), aName~value) 

не производит желаемый результат, потому что агрегатная функция length используется.

+0

Где используется длина и почему это не желательно? –

+1

Может быть, 'bind_rows (someDatasets)%>% group_by (dataset)%>% mutate (aName = paste0 (aName, 1: n()))%>% spread (набор данных, aValue)%>% mutate (aName = substr (aName, 1, 1)). – lukeA

+2

Добавьте вторичный идентификатор на основе группировки «aName» и «набора данных» (из вашего набора данных «tidyData»), а затем используйте 'dcast'. Например, если вы назвали вторичный идентификатор «ID», вы можете сделать «dcast (tidyDataWithID, aName + ID ~ dataset, value.var =« aValue »)». – A5C1D2H2I1M1N2O1R2T1

ответ

2

Как указано в комментариях @lukeA и @A Handcart и Mohair, вы можете добавить дополнительный идентификатор к своим данным, чтобы избежать дубликатов ключей .

library(dplyr) 
library(tidyr) 

tidyData = bind_rows(someDatasets) %>% 
    group_by(dataset, aName) %>% 
    mutate(id = paste0(aName, 1:n())) %>% 
    ungroup() %>% 
    select(-aName) 

# head(tidyData) 
# Source: local data frame [6 x 3] 
# 
# aValue dataset id 
# <dbl> <chr> <chr> 
# 1  1  ds1 a1 
# 2  2  ds1 a2 
# 3  3  ds1 a3 
# 4  4  ds1 b1 
# 5  5  ds1 b2 
# 6  10  ds2 a1 

id теперь уникально в пределах каждой группы (набора данных), чтобы мы могли продолжить распространение:

tidyData %>% 
    spread(dataset, aValue) %>% 
    mutate(id = substr(id, 1, 1)) 

# Source: local data frame [10 x 4] 
# 
#  id ds1 ds2 ds3 
# <chr> <dbl> <dbl> <dbl> 
# 1  a  1 10 100 
# 2  a  2 20 NA 
# 3  a  3 30 NA 
# 4  b  4 40 NA 
# 5  b  5 NA NA 
# 6  c NA 50 200 
# 7  c NA 60 300 
# 8  c NA NA 400 
+0

Спасибо. Второй вывод основан на уникальных 'aValue' и 'tidyData%>% group_by (aName, набор данных)%>% мутировать (ID = 1: n())%>% ungroup()%>% tidyr :: unite (col = "aName", aName, ID, sep = "#")%>% tidyr :: spread (набор данных, aValue)%>% tidyr :: separate (col = "aName", в = c ("aName", "ID"), remove = T, sep = "#")%>% dplyr :: select (- ID) 'выполнил задание. Я чувствую, что версия «tidyr» более многословна, чем «reshape2» - это неудачно. – Drey

+0

@Drey Извините, я забыл обновить верхнюю часть кода - см. Сейчас (немного меньше подробностей ...) – jakub

+0

retouring 'unite' и' separate' делает действительно более понятным. Еще раз спасибо и другим. – Drey

Смежные вопросы