2010-08-09 22 views
28

Tôi đã rất ngạc nhiên khi thấy rằng R sẽ ép buộc các yếu tố thành một số khi ghép các vec-tơ. Điều này xảy ra ngay cả khi các cấp là như nhau. Ví dụ:Làm thế nào để ghép các yếu tố, mà không cần chúng được chuyển đổi sang cấp nguyên?

> 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 

cách thành ngữ để làm điều này trong R (trong trường hợp này các vectơ này có thể khá lớn) là gì? Cảm ơn bạn.

Trả lời

27

Từ R Mailing list:

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

Để yếu tố 'cbind', làm

data.frame(facs[1 : 3], facs[4 : 5]) 
6

Ồ, tôi chưa bao giờ nhận ra điều đó. Đây là một công việc xung quanh:

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

Với kết quả:

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

Nó sẽ chỉ làm việc nếu hai vectơ có cùng cấp như ở đây.

+0

lớn nhờ ! Tôi đã chỉ ra rằng unlist (danh sách (facs [1: 3], facs [4: 5])) cũng hoạt động tốt nếu bạn không biết trước thời gian mà facs là một loại yếu tố. – Keith

+0

Cài đặt các cấp bằng tay theo cách này không hoạt động đối với vấn đề cụ thể của tôi. (Tôi có 0 cấp độ. Tôi có thể trừ 1 và sau đó xây dựng lại các yếu tố, nhưng, đó là giòn và vào cuối thấp hơn của phổ scrutabality, ngay cả đối với R.) Thay vào đó (hooray?) Tôi đã đi với 'unlist (danh sách (...)) '. –

8

Cách giải quyết thay thế là chuyển đổi hệ số thành một vector ký tự, sau đó chuyển đổi lại khi bạn đang ghép nối.

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

# Now choose between 
factor(x) 
# and 
factor(x, levels = levels(facs)) 
4

Đây là một R Gotcha thực sự tồi tệ. Dọc theo những dòng đó, đây là một trong số đó chỉ nuốt vài giờ thời gian của tôi.

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 

Dường như với tôi, bản sửa lỗi tốt hơn là Richie, gắn với tính cách.

> 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 

Miễn là bạn nhận được các mức được đặt chính xác, như Richie đề cập.

0

Dựa trên câu trả lời khác mà sử dụng chuyển đổi sang nhân vật Tôi đang sử dụng các chức năng sau đây để nối các yếu tố:

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

Bạn có thể sử dụng chức năng này cũng giống như bạn sẽ sử dụng c.

0

Dưới đây là một cách khác để thêm vào một biến yếu tố khi thiết lập là hơi khác nhau:

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 
0

Vì lý do này, tôi thích làm việc với các yếu tố bên trong data.frames:

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

và tập hợp con nó sử dụng tập hợp con() hoặc dplyr :: filter() vv thay vì chỉ mục hàng. Bởi vì tôi không có tiêu chí tập hợp con có ý nghĩa trong trường hợp này, tôi sẽ chỉ cần sử dụng đầu() và đuôi():

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

Sau đó, bạn có thể thao tác chúng khá dễ dàng, ví dụ:

dfc <- rbind(df1, df2) 
dfc$facs 
#[1] i  want to  be  an  integer 
#Levels: a an be factor i integer not to want 
Các vấn đề liên quan