2016-01-21 7 views
0

У меня довольно большой вектор списков (около 300,000 строк). Например, давайте рассмотрим следующее:Сочетание всех элементов в векторе списков на основе общего первого элемента каждого списка в векторе в R

vec = c( 
    list(c("A",10,11,12)), 
    list(c("B",10,11,15)), 
    list(c("A",10,12,12,16)), 
    list(c("A",11,12,16,17))) 

Теперь, я хочу сделать следующее:

Для каждого уникального первого элемента каждого списка в векторе, мне нужно все уникальные элементы происходящими, соответствующий это во всех списках в векторе вместе с соответствующими частотами.

выход будет несколько, как:

Для A, я бы элементы 10, 11 12, 16 & 17 с частотами 2,2,4,2 & 1 соответственно. Для B это было бы 10, 11, 15 с частотами 1,1,1.

Большое спасибо заранее, Ankur.

+2

(1) Проверьте кронштейны своего кода; (2) У вас есть список векторов или вектор векторов, но не вектор списков; (3) Что вы подразумеваете под 300 000 строк?; (4) Знаете ли вы, что если вы объединяете элементы символов с числовыми элементами в атомном векторе, весь вектор будет принудительно привязан к символу ?; (5) Пожалуйста, попробуйте уточнить название своей записи. – jbaums

+0

Я только что отредактировал, потому что я принимаю его плоский вектор и отсутствовала скобка. Пожалуйста, верните изменение, если вектор действительно вложен глубже. Я организовал код, чтобы показать простое вложение. – Spacedman

+0

(2) У меня есть вектор списков, как определено «vec». (3) Длина «vec» в моем коде составляет 300 000. Однако здесь мы можем работать с этим кратким примером. (4) Я знаю о принуждении. Предположим, что весь вектор является символом. @jbaums – James1991

ответ

3

Вот один из способов сделать это.

Во-первых, более простой способ создания списка является:

L <- list(c("A", 10, 11, 12), 
      c("B", 10, 11, 15), 
      c("A", 10, 12, 12, 16), 
      c("A", 11, 12, 16, 17)) 

Теперь вы можете разделить на первый символ, а затем пластинчатый все, кроме первого символа.

tapply(L, sapply(L, '[[', 1), function(x) 
    table(unlist(lapply(x, function(x) x[-1])))) 

## $A 
## 
## 10 11 12 16 17 
## 2 2 4 2 1 
## 
## $B 
## 
## 10 11 15 
## 1 1 1 

Расширения к списку, содержащему 300000 элементов одинакового размера:

L <- replicate(300000, c(sample(LETTERS, 1), sample(100, sample(3:4, 1)))) 

system.time(
    freqs <- tapply(L, sapply(L, '[[', 1), function(x) 
    table(unlist(lapply(x, function(x) x[-1])))) 
) 

## user system elapsed 
## 0.68 0.00 0.69 

Если вы хотите, чтобы отсортировать векторы результирующего списка, в соответствии с замечанием ФПА в поле ниже , вы можете просто изменить функцию, применяемую к группам L:

tapply(L, sapply(L, '[[', 1), function(x) 
    sort(table(unlist(lapply(x, function(x) x[-1]))), decreasing=TRUE)) 

## $A 
## 
## 12 10 11 16 17 
## 4 2 2 2 1 
## 
## $B 
## 
## 10 11 15 
## 1 1 1 

Если вы хотите только скопировать значения для определенной группы, например. группа A (векторы, которые начинаются с A), вы можете либо подмножество предыдущего результата:

L2 <- tapply(L, sapply(L, '[[', 1), function(x) 
    sort(table(unlist(lapply(x, function(x) x[-1]))), decreasing=TRUE), 
    simplify=FALSE) 

L2$A 

(Обратите внимание, что я добавил simplify=FALSE так, что это будет работать, даже если количество уникальных элементов одинаковы для группы)

Это более эффективно выполнять только операции для группы интересов, хотя, в этом случае может быть следующее лучше:.

sort(table(unlist(
    lapply(split(L, sapply(L, '[[', 1))$A, function(x) x[-1]) 
)), decreasing=TRUE) 

где split первые расколы L в группы по первому элементу векторов, и тогда мы подмножим только группу A с $A.

+1

Аккуратно, мое единственное беспокойство по поводу таких решений может заключаться в создании длинных векторов из 300 000 элементов (которые затем подаются в «таблицу»). Это может быть медленнее, чем подход, который циклически и постепенно создает таблицу из элементов. Продолжайте, масштабируйте данные до 300 000 элементов и посмотрите, сколько времени потребуется! (ответ: 3 секунды в списке длин 300 000 с ~ 10 элементами в каждом!) – Spacedman

+0

@Spacedman - хорошая точка, но все равно под сек. – jbaums

+0

Спасибо @jbaums. Что делать, если я хочу сортировать внутренние списки на основе уменьшения порядка частот? – James1991