Конвертировать фрейм данных в матрицу «ранжированных списков» на основе уникальных значений в столбце - PullRequest
0 голосов
/ 03 января 2019

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

df = data.frame(c("A", "A", "B", "B", "C", "D", "D", "D", "E"), 
        c(0.1, 0.3, 0.1, 0.8, 0.4, 0.7, 0.5, 0.2, 0.1),
        c("v1", "v2", "v1", "v3", "v4", "v2", "v3", "v4", "v2"))

colnames(df) = c("entry", "value", "point")
df = df[order(df$entry, -df$value),]

df
   entry value point
2     A   0.3    v2
1     A   0.1    v1
4     B   0.8    v3
3     B   0.1    v1
5     C   0.4    v4
6     D   0.7    v2
7     D   0.5    v3
8     D   0.2    v4
9     E   0.1    v2

Я хотел бы преобразовать его в конечном итоге в матрицу «ранжированных списков», в которой в качестве строк указаны уникальные значения в столбце entry, а количество столбцов должно быть равно числу максимум уникальных элементов в столбце point для данного entry. В этом примере это будет 3. Каждая строка должна быть заполнена соответствующими значениями из столбца point, отсортированными по убыванию на основе соответствующих элементов в value (например, строка A должна иметь v2 в качестве значения в первый столбец). Если entry имеет points меньше, чем количество столбцов в матрице, остальная часть строки должна быть заполнена NAs.

Итак, ожидаемый результат должен выглядеть примерно так:

>df
   1   2   3  
A  v2  v1  NA 
B  v3  v1  NA 
C  v4  NA  NA 
D  v2  v3  v4
E  v2  NA  NA

До сих пор я пытался создать какую-то таблицу сопряженности, используя

with(df, table(df$point, df$entry))

, но, конечно, мои фактические данные находятся в порядке миллионов записей, и приведенная выше команда увеличивает объем ОЗУ даже при установке значения 100 entries с парой сотен уникальных points. Я также попробовал

xtabs(~ entry + point, data=df)

с такими же результатами на моих реальных данных. Затем я попытался разбить его на упорядоченные списки, используя

df = split(df$point, df$entry)

, который работает нормально и достаточно быстро, buuuuut .. теперь у меня проблемы с преобразованием его в матрицу результата. Что-то в этом роде, вероятно,

matrix(sapply(df, function(x) unlist(x)), nrow=length(df), ncol=max(sapply(df, length)))

или сначала инициализировать матрицу и сделать что-то rbind или что-то?

res = matrix(NA, nrow=length(df), ncol=max(sapply(df, length)))
rownames(res) = names(df)
....

Не могли бы вы помочь?

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Попробуйте использовать by, чтобы разделить на запись и построить необходимые векторы.Для строк одинаковой длины в конечной матрице добавьте NA, если необходимо, чтобы нижнее значение 3 можно было изменить на любое количество необходимых столбцов.

vec_list <- by(df, df$entry, function(sub) {
    vec <- as.character(sub[order(-sub$value),]$point)    
    c(vec, rep(NA, 3 - length(vec)))    
})

final_matrix <- do.call(rbind, vec_list)

final_matrix
#   [,1] [,2] [,3]
# A "v2" "v1" NA  
# B "v3" "v1" NA  
# C "v4" NA   NA  
# D "v2" "v3" "v4"
# E "v2" NA   NA 

Rextester Demo

0 голосов
/ 03 января 2019

С dplyr:

df %>% 
   group_by(entry) %>% 
   mutate(unq=rank(rev(value))) %>% 
   select(-value) %>% 
   tidyr::spread(unq,point)
# A tibble: 5 x 4
# Groups:   entry [5]
  entry `1`   `2`   `3`  
  <fct> <fct> <fct> <fct>
1 A     v2    v1    NA   
2 B     v3    v1    NA   
3 C     v4    NA    NA   
4 D     v2    v3    v4   
5 E     v2    NA    NA   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...