2011-04-29 2 views
4

У меня есть следующий кадр данных в R:неразъемные список, слияние факторов

c1 c2 
1 10 a 
2 20 a 
3 30 b 
4 40 b 

Я тогда split его следующим образом: z = lapply(split(test$c1, test$c2), function(x) {cut(x,2)}) . z затем:

$a 
[1] (9.99,15] (15,20] 
Levels: (9.99,15] (15,20] 

$b 
[1] (30,35] (35,40] 
Levels: (30,35] (35,40] 

Я хотел бы, чтобы затем объединить факторы назад unsplitting список unsplit(z, test$c2). Это генерирует предупреждение:

[1] (9.99,15] (15,20] <NA>  <NA>  
Levels: (9.99,15] (15,20] 
Warning message: 
In `[<-.factor`(`*tmp*`, i, value = 1:2) : 
    invalid factor level, NAs generated 

Я хотел бы взять объединение всех уровней факторов, а затем неразбитый так, что эта ошибка не бывает:

z$a = factor(z$a, levels=c(levels(z$a), levels(z$b))) 
unsplit(z, test$c2) 
[1] (9.99,15] (15,20] (30,35] (35,40] 
Levels: (9.99,15] (15,20] (30,35] (35,40]  

В моей реальной фрейме данных у меня есть очень большой список, поэтому мне нужно перебрать все элементы списка (а не только два). Каков наилучший способ сделать это?

ответ

4

If Я правильно понял ваш вопрос, я думаю, вы делаете это немного сложнее, чем нужно. Вот одно решение, использующее plyr. Мы будем группировать по переменной c2:

require(plyr) 
ddply(test, "c2", transform, newvar = cut(c1, 2)) 

, которая возвращает:

c1 c2 newvar 
1 10 a (9.99,15] 
2 20 a (15,20] 
3 30 b (30,35] 
4 40 b (35,40] 

и имеет структуру:

'data.frame': 4 obs. of 3 variables: 
$ c1 : num 10 20 30 40 
$ c2 : Factor w/ 2 levels "a","b": 1 1 2 2 
$ newvar: Factor w/ 4 levels "(9.99,15]","(15,20]",..: 1 2 3 4 
+0

Да, это именно то, что я хотел сделать. Большое вам спасибо за вашу помощь! для -Alex- – Alex

4

Можете ли вы не просто unlist()z вместо этого?

> unlist(z) 
     a1  a2  b1  b2 
(9.99,15] (15,20] (30,35] (35,40] 
Levels: (9.99,15] (15,20] (30,35] (35,40] 

или без имен результирующего фактора:

> unlist(z, use.names=FALSE) 
[1] (9.99,15] (15,20] (30,35] (35,40] 
Levels: (9.99,15] (15,20] (30,35] (35,40] 

Вы можете объединить все вместе в простой однострочника, который не нуждается в дополнительных пакетов:

> (test2 <- within(test, newvar <- unlist(lapply(split(c1, c2), cut, 2)))) 
    c1 c2 newvar 
1 10 a (9.99,15] 
2 20 a (15,20] 
3 30 b (30,35] 
4 40 b (35,40] 
+0

Я думаю, что ответ ниже сделал мой код очень прост. Твой тоже отлично работает, но мне просто нужно добавить его в фрейм данных. Спасибо за вашу помощь! -Alex – Alex

+0

@Alex Неясно, вы хотите вставить это обратно в исходные данные. Я обновляю свой ответ, чтобы упростить весь процесс - 1 строка кода делает все, что вам нужно, без дополнительных пакетов и т. Д. –

+0

Это отлично работает! Спасибо. Ценю вашу помощь. – Alex

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

  • Нет связанных вопросов^_^