2015-01-10 2 views
2

Я хотел бы достичь в R следующего: data.frameexpand.grid с отдельными переменным для каждого столбца

i1 i2 i3 
1 A1 A2 A3 
2 No A2 A3 
3 A1 No A3 
4 No No A3 
5 A1 A2 No 
6 No A2 No 
7 A1 No No 
8 No No No 

В каждой колонке переменные может быть либо Сцепленная строкой «А» и номер столбца или «Нет». data.frame должен содержать все возможные комбинации.

Моя идея заключалась в использовании expand.grid, но я не знаю, как создать list динамически. Или есть лучший подход?

expand.grid(list(c("A1", "No"), c("A2", "No"), c("A3", "No"))) 

ответ

6

Я думаю, вы можете создать свою собственную функцию помощника, что-то вроде этого

MyList <- function(n) expand.grid(lapply(paste0("A", seq_len(n)), c, "No")) 

Тогда просто передать его количество элементов (например, 3)

MyList(3) 
# Var1 Var2 Var3 
# 1 A1 A2 A3 
# 2 No A2 A3 
# 3 A1 No A3 
# 4 No No A3 
# 5 A1 A2 No 
# 6 No A2 No 
# 7 A1 No No 
# 8 No No No 

В качестве альтернативы вы также можете попробовать data.table с эквивалентом CJ, который должен быть намного более эффективным, чем expand.grid для большого n

library(data.table) 
DTCJ <- function(n) do.call(CJ, lapply(paste0("A", seq_len(n)), c, "No")) 
DTCJ(3) # will return a sorted cross join 
# V1 V2 V3 
# 1: A1 A2 A3 
# 2: A1 A2 No 
# 3: A1 No A3 
# 4: A1 No No 
# 5: No A2 A3 
# 6: No A2 No 
# 7: No No A3 
# 8: No No No 
+0

Что? Нет 'CJ'? Этот ответ разочаровывает ... ;-) – A5C1D2H2I1M1N2O1R2T1

+0

@ Ананда, к сожалению, 'CJ' не работает с объектом списка, и я собирался спросить об этом Аруна. Может быть, akruns 'data.frame' будет работать, не знаю –

+0

Я думаю, что я только что видел do.call, чтобы заставить его работать именно так. – A5C1D2H2I1M1N2O1R2T1

2

Другой вариант заключается в использовании Map с expand.grid

n <- 3 
expand.grid(Map(c, paste0('A', seq_len(n)), 'NO')) 

Или

expand.grid(as.data.frame(rbind(paste0('A', seq_len(n)),'NO'))) 
0

Другой вариант, используя только самые основные функции в R, является использование индексы:

df <- data.frame(V1 = c('A','A','A', 'A',rep('No',4)), V2 = c('A','A','No','No','A','A','No','No'), V3 = c('A','No','A','No','A','No','A','No'), stringsAsFactors = FALSE) 

, чтобы получить строки и Col индексы элементов, которые мы должны изменить:

rindex <- which(df != 'No') %% nrow(df) 
cindex <- ceiling(which(df != 'No')/nrow(df)) 

решение в основном один вкладыш:

df[matrix(c(rindex,cindex),ncol=2)] <- paste0(df[matrix(c(rindex,cindex),ncol=2)],cindex) 

> df 

    V1 V2 V3 
1 A1 A2 A3 
2 A1 A2 No 
3 A1 No A3 
4 A1 No No 
5 No A2 A3 
6 No A2 No 
7 No No A3 
8 No No No 
+0

О чем 'df' вы имеете в виду? ОП не предоставил набор данных. Я бы предположил, что они на самом деле пытаются избежать создания. –

+0

@DavidArenburg, см. Мое редактирование. Я построил df, который использовал OP при запросе решения. – hvollmeier

+0

Извините, я не вижу этого 'df' нигде. Все предоставленные ОП были его желательным выходом. –

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