2017-02-21 15 views
-1

Предположим, что у меня есть список, подобный этому:Каков самый быстрый способ сокращения элементов списка по частоте?

set.seed(12731) 
out <- lapply(1:sample.int(10, 1), function(x){sample(letters[1:4], x, replace = T)}) 

[[1]] 
[1] "b" 

[[2]] 
[1] "d" "c" 

[[3]] 
[1] "b" "a" "a" 

[[4]] 
[1] "d" "d" "b" "c" 

[[5]] 
[1] "d" "d" "c" "c" "b" 

[[6]] 
[1] "b" "d" "b" "d" "c" "c" 

[[7]] 
[1] "a" "b" "d" "d" "b" "a" "d" 

Я хотел бы иметь векторов длины одной, заданной элементом высокой частоты в списке. Обратите внимание, что может иметь векторы длины> 1, если нет дубликатов. Таблица частот, как это:

table(unlist(out))[order(table(unlist(out)), decreasing = T)] 

b c d a 
16 14 13 12 

исход примера что-то вроде этого:

list("b", "c", "b", "b", "b", "b", "b") 

REMARK Можно иметь векторов длины> 1, если нет дубликатов ,

out <- lapply(1:sample.int(10, 1), function(x){sample(letters[1:4], x, replace = T)}) 
length(out) 
[1] 10 
out[[length(out)+1]] <- c("L", "K") 
out 
[[1]] 
[1] "c" 

[[2]] 
[1] "d" "a" 

[[3]] 
[1] "c" "b" "a" 

[[4]] 
[1] "b" "c" "b" "c" 

[[5]] 
[1] "a" "a" "d" "c" "d" 

[[6]] 
[1] "d" "b" "d" "d" "d" "a" 

[[7]] 
[1] "d" "b" "c" "c" "d" "c" "a" 

[[8]] 
[1] "d" "a" "d" "b" "d" "a" "b" "d" 

[[9]] 
[1] "a" "b" "b" "b" "c" "c" "a" "c" "d" 

[[10]] 
[1] "d" "d" "d" "a" "d" "d" "c" "c" "a" "c" 

[[11]] 
[1] "L" "K" 

Ожидаемые результаты:

list("c", "d", "c", "c", "d", "d", "d", "d", "d", "d", c("L", "K")) 
+3

Вам нужно «set.seed» –

+0

TX, вы имеете в виду, чтобы сделать пример более четким? –

+1

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

ответ

1

Я считаю, что это должно работать п или то, что вы ищете.

# get counts for entire list and order them 
myRanks <- sort(table(unlist(out)), decreasing=TRUE) 

Это производит

myRanks 

b c d a 
10 9 5 4 


# calculate if most popular, then second most popular, ... item shows up for each list item 
sapply(out, function(i) names(myRanks)[min(match(i, names(myRanks)))]) 
[1] "b" "b" "b" "c" "b" "b" "b" 

Здесь sapply проходит через каждый элемент списка и возвращает вектор. Он применяет функцию, которая выбирает имя первого элемента (через min) таблицы myRanks, которая появляется в элементе списка, используя match.


В случае нескольких элементов, имеющих одинаковое количество (дубли) в таблице myRanks, следующий код должен возвращать список из главных наблюдений в пункте списка:

sapply(out, 
    function(i) { 
     intersect(names(myRanks)[myRanks == max(unique(myRanks[match(i, names(myRanks))]))], 
       i)}) 

Здесь имена myRanks, которые имеют то же значение, что и значение в элементе списка с наивысшим значением в myRanks, пересекаются с именами, присутствующими в элементе списка, чтобы возвращать значения только в обоих наборах.

+0

Мне очень нравится, что ваш ответ чист, но не могли бы вы прочитать мое замечание. –

+1

Мне тоже удалось это сделать: myRanks <- sort (table (unlist (out)), убывающий = TRUE) sapply (out, function (i) {inter <- myRanks [intersect (i, names (myRanks)))] имена (которые (inter == max (inter)))}) –

0

Это должно работать:

set.seed(12731) 
out <- lapply(1:sample.int(10, 1), function(x){sample(letters[1:4], x, replace = T)}) 
out 
#[[1]] 
#[1] "b" 

#[[2]] 
#[1] "c" "b" 

#[[3]] 
#[1] "b" "b" "b" 

#[[4]] 
#[1] "d" "c" "c" "d" 

#[[5]] 
#[1] "d" "b" "a" "a" "c" 

#[[6]] 
#[1] "a" "b" "c" "b" "c" "c" 

#[[7]] 
#[1] "a" "c" "d" "b" "d" "c" "b" 

tbl <- table(unlist(out))[order(table(unlist(out)), decreasing = T)] 
sapply(out, function(x) intersect(names(tbl), x)[1]) 
# [1] "b" "b" "b" "c" "b" "b" "b" 

[EDIT]

set.seed(12731) 
out <- lapply(1:sample.int(10, 1), function(x){sample(letters[1:4], x, replace = T)}) 
out[[length(out)+1]] <- c("L", "K") 
out 
#[[1]] 
#[1] "b" 

#[[2]] 
#[1] "c" "b" 

#[[3]] 
#[1] "b" "b" "b" 

#[[4]] 
#[1] "d" "c" "c" "d" 

#[[5]] 
#[1] "d" "b" "a" "a" "c" 

#[[6]] 
#[1] "a" "b" "c" "b" "c" "c" 

#[[7]] 
#[1] "a" "c" "d" "b" "d" "c" "b" 

#[[8]] 
#[1] "L" "K" 

tbl <- table(unlist(out))[order(table(unlist(out)), decreasing = T)] 

#tbl 
#b c d a K L 
#10 9 5 4 1 1 

lapply(out, function(x) names(tbl[tbl==max(tbl[names(tbl) %in% intersect(names(tbl), x)])])) 

#[[1]] 
#[1] "b" 

#[[2]] 
#[1] "b" 

#[[3]] 
#[1] "b" 

#[[4]] 
#[1] "c" 

#[[5]] 
#[1] "b" 

#[[6]] 
#[1] "b" 

#[[7]] 
#[1] "b" 

#[[8]] 
#[1] "K" "L" 
+0

TX, но это не то, что я имел в виду. Частоту нужно вычислять со всеми элементами списка, а не с отдельными элементами. Именно так я вычислил его в примере. –

+0

обновлено согласно вашему требованию @ Mario GS –

+0

Это почти то, что я ожидал, не могли бы вы прочитать мое замечание? –