2015-01-12 25 views
5

Tôi có rất nhiều bộ biến như thế này:Làm thế nào tốt nhất để sụp đổ hai yếu tố bằng NA vào một biến

Var1 Var2 
"Asian"  NA 
    NA "Black" 
"White"  NA 

Tôi muốn để thuận tiện nhận được chúng vào biểu mẫu này:

Race 
"Asian" 
"Black" 
"White" 

tôi đã thử một số nội dung như:

Race <- ifelse(is.na(Var1), Var2, Var1) 

Nhưng điều này chuyển đổi giá trị thành số cho các cấp và nu mbers không phù hợp (ví dụ: sản lượng đó là 1, 1, 2). Có cách nào thuận tiện để làm điều này (lý tưởng với mã ngắn, tự giải thích)? (Bạn có thể nhận ra điều này với as.character, nhưng đó có phải là một cách tốt hơn.)

+0

Bạn có phải làm việc với các yếu tố không? Sử dụng các biểu diễn ký tự bạn có thể làm: 'pmax (Var1, Var2, na.rm = TRUE)' – thelatemail

+0

@thelatemail, tôi vừa thử điều đó, nhưng nó không hoạt động đối với tôi. Tôi có cần phải áp dụng 'as.character' cho tất cả các biến đầu tiên không? – gung

+0

@thelatemail, có vẻ như nó hoạt động nếu tôi làm 'as.character' trước. Nếu bạn có thể nhét cái này vào một chức năng thuận tiện, tôi sẽ chấp nhận nó. – gung

Trả lời

4

Với một chuyển đổi trung gian qua as.character:
Giả sử đây là của bạn dữ liệu:

dat <- data.frame(Var1=c("Asian",NA,"White"),Var2=c(NA,"Black",NA)) 

do.call(pmax,c(lapply(dat,as.character),na.rm=TRUE)) 
#[1] "Asian" "Black" "White" 

Nếu bạn cần phải làm việc trên một tập hợp con đặc biệt mà bạn có thể làm:

do.call(pmax,c(lapply(dat[c("Var1","Var2")],as.character),na.rm=TRUE)) 

Một thay thế không đòi hỏi as.character sẽ là:

dat[cbind(1:nrow(dat),max.col(!is.na(dat)))] 
#[1] "Asian" "Black" "White" 
+0

Trên thực tế, khung dữ liệu của tôi có nhiều, nhiều tập hợp các biến như thế này. Vì vậy, tôi không thể hoạt động trên toàn bộ df theo cách này. Tôi đã viết một hàm đơn giản: 'collapse <- function (v1, v2) pmax (as.character (v1), as.character (v2), na.rm = T)', có vẻ như hoạt động. – gung

+0

Cảm ơn sự giúp đỡ của bạn. – gung

+0

Ý tưởng gọn gàng! Điều này có thể khái quát hơn một chút về các tình huống trong đó có nhiều hơn hai cột cần được thu gọn thành một: 'áp dụng (df [c (" Var1 "," Var2 ")], 1, max, na.rm = TRUE)' –

2

gì về giải pháp này ?:

ind <- apply(df, 1, function(x) which(!is.na(x))) 
df[cbind(seq_along(ind), ind)] 
[1] "Asian" "Black" "White" 
+0

Điều này có thể được đơn giản hóa thành 'df [cbind (seq_len (nrow (df)), is.na (df $ Var1) + 1)]' (ít nhất là trong trường hợp 2 cột). – jbaums

+0

Cảm ơn ý tưởng. – gung

1

Một giải pháp (khá lạ Tôi đồng ý và khá ngắn, các cột của bạn cần phải được nhân vật như nó có vẻ là trong ví dụ của bạn):

> library(tidyr) 
> unite(replace(df, is.na(df), ""), V, c(Var1, Var2), sep=''))$V 
#[1] "Asian" "Black" "White" 

Hoặc, nó có thể là mạo hiểm khi dùng gsub nhưng ở đây NA là một phần của một chuỗi nhân vật rất an toàn:

> gsub("NA", "", unite(df, V, c(Var1, Var2), sep='')$V) 
#[1] "Asian" "Black" "White" 
+0

Cảm ơn lời khuyên. – gung

Các vấn đề liên quan