2012-07-09 368 views
0

我有一個有兩列的數據框,並且想要創建第三列,它本質上是一個布爾值,用於列2是否包含一組特定的值。基於另一列創建一個新的數據框列

f <- data.frame(name=c("John", "Sara", "David", "Chad"), 
       car=c("Honda|Ford", "BMW", "Toyota|Chevy|Ford", 
       "Toyota|Chevy|Ford|Honda")) 

我做的第一件事是刪除|從第二列的每個字符串,並放置那些價值在第三列

library(stringr) 
g = str_replace_all(f$car, "[^[:alnum:]]", " ") 
f$make = c(g) 
f 

我現在要怎麼做,如果創建另一列,這將是一個布爾值,1如果make包含一個共同的汽車和0如果它包含一輛不常見的汽車。

common = c("Honda", "Ford", "Toyota", "Chevy") 
not_common = c("BMW", "Lexus", "Acura") 

我試過幾件事情,包括stringr包和ifelse來產生下面的輸出。

name      car     make  common 
1 John    Honda|Ford    Honda Ford   1 
2 Sara      BMW      BMW   0 
3 David  Toyota|Chevy|Ford  Toyota Chevy Ford   1 
4 Chad Toyota|Chevy|Ford|Honda Toyota Chevy Ford Honda   1 

因爲它可能同時擁有常見和不常見的車作爲入門,不凡的化妝應覆蓋常見品牌和該行應採取值0的公共列。因此,如果一個條目同時包含寶馬和福特,則該條目在共同欄中應該爲0。

任何人都可以幫助完成此任務。

哦,這是我用stringr軟件包試過的,但它不起作用。

common = c("Honda", "Ford", "Toyota", "Chevy") 
not_common = c("BMW", "Lexus", "Acura") 
common_match <- str_c(common) 
not_match <- str_c(not_common) 

main <- function(df) { 
    f$new_make <- str_detect(f$make, common_match) 
    df 
} 

main(f) 

謝謝!

回答

2

的另一種方法和比較

f2 <- f[rep(1:4,50000),] 
system.time({ 
v <- sapply(f2$make, strsplit, " ") 
sapply(v, function(x) max(1-not_common %in% x)*max(common %in% x)) 
}) 
user system elapsed 
7.94 0.01 8.00 

system.time(sapply(f2$car,function(x) ifelse(length(grep("BMW|Lexus|Acura",x))>0,0,1))) 
user system elapsed 
28.72 0.04 28.87 
2

不確定這是否是最有效的方法,但試試這個使用grepifelse的方法應用於每個值f$car|字符僅僅意味着or用於組合grep內的搜索字詞,並且與數據中的分隔符無關。

f$common <- sapply(f$car,function(x) ifelse(length(grep("BMW|Lexus|Acura",x))>0,0,1)) 

結果:

> f 
    name      car common 
1 John    Honda|Ford  1 
2 Sara      BMW  0 
3 David  Toyota|Chevy|Ford  1 
4 Chad Toyota|Chevy|Ford|Honda  1 
相關問題