2012-07-09 216 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 
相关问题