2011-01-31 3 views
9

У меня есть 2 столбца данных с данными того же типа (строки).Уровни соединения двух столбцов в R

Я хочу присоединиться к уровням столбцов. то есть. мы имеем:

col1 col2 
Bob John 
Tom Bob 
Frank Jane 
Jim Bob 
Tom Bob 
... ... (and so on) 

Теперь col1 имеет 4 уровня (Боб, Том Фрэнк, Джим) и col2 имеет 3 уровня (Джон, Джейн, Боб)

Но я хочу, обе колонки, чтобы все уровни фактора (Боб, Том, Фрэнк, Джим, Джейн, Джон), чтобы впоследствии заменить каждый из «имен» с уникальным идентификатором, таким образом, что конечный результат будет:

col1 col2 
1  5 
2  1 
3  6 
4  1 
2  1 

, что Боб -> 1 , Tom -> 2 и т. Д. В обеих колонках.

Любые идеи :)?

Редактировать: Спасибо всем за замечательные ответы! Вы все удивительное, насколько я знаю :)

ответ

6

Вы хотите факторы, которые включают в себя все уникальные имена из обеих колонок.

col1 <- factor(c("Bob", "Tom", "Frank", "Jim", "Tom")) 
col2 <- factor(c("John", "Bob", "Jane", "Bob", "Bob")) 
mynames <- unique(c(levels(col1), levels(col2))) 
fcol1 <- factor(col1, levels = mynames) 
fcol2 <- factor(col2, levels = mynames) 

EDIT: немного лучше, если заменить третью строку с этим:

mynames <- union(levels(col1), levels(col2)) 
2

мог бы поклясться, это не сработало, когда я писал мерзость ниже, но это делает сейчас:

## self contained example: 
txt <- "col1 col2 
Bob John 
Tom Bob 
Frank Jane 
Jim Bob 
Tom Bob" 
dat <- read.table(textConnection(txt), header = TRUE) 

Просто вычислить уникальный набор уровней и принуждать каждый colX к фактору:

> dat3 <- dat 
> lev <- as.character(unique(unlist(sapply(dat, levels)))) 
> dat3 <- within(dat3, col1 <- factor(col1, levels = lev)) 
> dat3 <- within(dat3, col2 <- factor(col2, levels = lev)) 
> str(dat3) 
'data.frame': 5 obs. of 2 variables: 
$ col1: Factor w/ 6 levels "Bob","Tom","Frank",..: 1 2 3 4 2 
$ col2: Factor w/ 6 levels "Bob","Tom","Frank",..: 5 1 6 1 1 
> data.matrix(dat3) 
    col1 col2 
[1,] 1 5 
[2,] 2 1 
[3,] 3 6 
[4,] 4 1 
[5,] 2 1 

[Оригинал:, чтобы показать, как тупо сложный и запутанном можно записать R код это один пытается действительно трудно] Не уверен, что это особенно eleg муравей (и это не так), но ...

Мы первые unlist данные:

tmp <- unlist(dat) 

затем вычислить уникальные уровни

lev <- as.character(unique(tmp)) 

, а затем перестраивать tmp (сверху) обратно в те же размеры, что и исходные данные, преобразовать в data.frame (сохранение строк), привязать к этому кадру данных, создав фактор с уровнями lev, вычисленный выше, и, наконец, принуждение к кадру данных.

dat2 <- data.frame(lapply(data.frame(matrix(tmp, ncol = ncol(dat)), 
            stringsAsFactors = FALSE), 
          FUN = factor, levels = lev)) 

Что дает:

> dat2 
    X1 X2 
1 Bob John 
2 Tom Bob 
3 Frank Jane 
4 Jim Bob 
5 Tom Bob 
> sapply(dat2, levels) 
    X1  X2  
[1,] "Bob" "Bob" 
[2,] "Tom" "Tom" 
[3,] "Frank" "Frank" 
[4,] "Jim" "Jim" 
[5,] "John" "John" 
[6,] "Jane" "Jane" 
> data.matrix(dat2) 
    X1 X2 
[1,] 1 5 
[2,] 2 1 
[3,] 3 6 
[4,] 4 1 
[5,] 2 1 
11
x <- structure(list(col1 = structure(c(1L, 4L, 2L, 3L, 4L), .Label = c("Bob", "Frank", "Jim", "Tom"), class = "factor"), col2 = structure(c(3L, 1L, 2L, 1L, 1L), .Label = c("Bob", "Jane", "John"), class = "factor")), .Names = c("col1", "col2"), class = "data.frame", row.names = c(NA, -5L)) 

Сделать простое объединение имен факторов:

both <- union(levels(x$col1), levels(x$col2)) 

И relevel два фактора:

x$col1 <- factor(x$col1, levels=both) 
x$col2 <- factor(x$col2, levels=both) 

После редактирования: добавлен пример, чтобы сделать числовые значения из факторов

Можно просто преобразовать уровни фактора в числовые значения, например,:

as.numeric(x$col1) 

Или более проще, лучше решение, основанное на намеком @Gavin Симпсона ниже в одном шаге:

data.matrix(x) 
+1

Аккуратный, чистый и быстро. Великий. ИМХО лучше, чем ответить на то, что @Gavin опубликовал, хотя я бы предпочел «data.frame (lapply (...» решение, из чистой лени. – aL3xa

+1

+1 вы избили меня до разумного ответа. Можете ли вы изменить свой 'as.numeric (x $ col1) 'только для' data.matrix (x) '? Если это так, я удалю свой лишний ответ. –

+1

@ aL3xa - эй, честно говоря, я должен получить баллы за количество введенных символов !?; -) –

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