Уровни объединения двух столбцов

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

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

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

то есть Bob → 1, Tom → 2 и т.д. в обоих столбцах.

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

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

Ответ 1

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

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

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))

И соедините два фактора:

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

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

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

as.numeric(x$col1)

Или более простое, более приятное решение, основанное на подсказке @Gavin Simpson ниже за один шаг:

data.matrix(x)

Ответ 3

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

## 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-код, который он очень усердно пытается!] Не уверен, что это особенно элегантно (и это не так), но...

Сначала мы заблокируем данные:

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

Ответ 4

В базовом пакете R. есть функция interaction(). В пакете для survival также есть функция strata().