Как объединить факторы без их преобразования в целочисленный уровень? - PullRequest
37 голосов
/ 09 августа 2010

Я был удивлен, увидев, что R объединяет факторы в число при объединении векторов. Это происходит даже тогда, когда уровни одинаковы. Например:

> facs <- as.factor(c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
> facs
[1] i       want    to      be      a       factor  not     an      integer
Levels: a an be factor i integer not to want
> c(facs[1 : 3], facs[4 : 5])
[1] 5 9 8 3 1

каков идиоматический способ сделать это в R (в моем случае эти векторы могут быть довольно большими)? Спасибо.

Ответы [ 8 ]

33 голосов
/ 21 февраля 2011

Из списка рассылки R :

unlist(list(facs[1 : 3], facs[4 : 5]))

Для факторов cbind выполните

data.frame(facs[1 : 3], facs[4 : 5])
9 голосов
/ 10 августа 2010

Альтернативный обходной путь - преобразовать фактор в символьный вектор, а затем преобразовать обратно при конкатенации с окончанием.

cfacs <- as.character(facs)
x <- c(cfacs[1:3], cfacs[4:5]) 

# Now choose between
factor(x)
# and
factor(x, levels = levels(facs))
6 голосов
/ 09 августа 2010

Ух ты, я так и не понял, что это сделал. Вот обходной путь:

x <- c(facs[1 : 3], facs[4 : 5]) 
x <- factor(x, levels=1:nlevels(facs), labels=levels(facs))
x

С выходом:

[1] i    want to   be   a   
Levels: a an be factor i integer not to want

Это будет работать, только если два вектора имеют те же уровни, что и здесь.

4 голосов
/ 31 марта 2014

Это действительно плохая буква R.Вдобавок к этому, вот тот, который проглотил несколько часов моего времени.

x <- factor(c("Yes","Yes","No", "No", "Yes", "No"))
y <- c("Yes", x)

> y
[1] "Yes" "2"   "2"   "1"   "1"   "2"   "1"  
> is.factor(y)
[1] FALSE

Мне кажется, лучшее решение - это Ричи, которое приводит к характеру.

> y <- c("Yes", as.character(x))
> y
[1] "Yes" "Yes" "Yes" "No"  "No"  "Yes" "No" 
> y <- as.factor(y)
> y
[1] Yes Yes Yes No  No  Yes No 
Levels: No Yes

Пока вы правильно устанавливаете уровни, как упоминает Ричи.

3 голосов
/ 16 мая 2018

С тех пор, как этот вопрос был задан, Хэдли Уикхем создал пакет forcats с функцией fct_c, предназначенный для подобных задач.

> library(forcats)
>  facs <- as.factor(c("i", "want", "to", "be", "a", "factor", "not", "an", 
"integer"))
> fct_c(facs[1:3], facs[4:5])
[1] i    want to   be   a
Levels: a an be factor i integer not to want

В качестве примечания, fct_c также не являетсяне одурачены конкатенацией факторов, использующих несовпадающие числовые кодировки:

> x <- as.factor(c('c', 'z'))
> x
[1] c z
Levels: c z
> y <- as.factor(c('a', 'b', 'z'))
> y
[1] a b z
Levels: a b z
> c(x, y)
[1] 1 2 1 2 3
> fct_c(x, y)
[1] c z a b z
Levels: c z a b
> as.numeric(fct_c(x, y))
[1] 1 2 3 4 2
1 голос
/ 31 мая 2017

По этой причине я предпочитаю работать с факторами внутри data.frames:

df <- data.frame(facs = as.factor(
      c("i", "want", "to", "be", "a", "factor", "not", "an", "integer") ))

и подмножество его, используя subset () или dplyr :: filter () и т. Д. Вместо индексов строк. Поскольку в этом случае у меня нет значимых критериев подмножества, я просто буду использовать head () и tail ():

df1 <- head(df, 4)
df2 <- tail(df, 2)

Тогда вы можете довольно легко ими манипулировать, например ::100100

dfc <- rbind(df1, df2)
dfc$facs
#[1] i       want    to      be      an      integer
#Levels: a an be factor i integer not to want
1 голос
/ 19 октября 2016

На основании других ответов, в которых используется преобразование в символ, я использую следующую функцию для объединения факторов:

concat.factor <- function(...){
  as.factor(do.call(c, lapply(list(...), as.character)))
}

Вы можете использовать эту функцию так же, как и c.

0 голосов
/ 05 ноября 2016

Вот еще один способ добавить факторную переменную, когда установка немного отличается:

facs <- factor(1:3, levels=1:9,
               labels=c("i", "want", "to", "be", "a", "factor", "not", "an", "integer"))
facs
# [1] i       want    to      be      a       factor  not     an      integer
# Levels: a an be factor i integer not to want
facs[4:6] <- levels(facs)[4:6]
facs
# [1] i      want   to     be     a      factor
# Levels: i want to be a factor not an integer
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...