2017-03-02 32 views
5

Hãy xem xét các yếu tố sau đâyĐếm số "0" trong yếu tố này

x = factor(c("1|1","1|0","1|1","1|1","0|0","1|1","0|1")) 

Tôi muốn đếm số lần xuất hiện của nhân vật "0" trong yếu tố này. Giải pháp duy nhất tôi đã tìm thấy cho đến nay là

sum(grepl("0",strsplit(paste(sapply(x, as.character), collapse=""), split="")[[1]])) 
# [1] 4 

Giải pháp này có vẻ rất phức tạp cho quá trình đơn giản như vậy. Có một lựa chọn tốt hơn? (Như quá trình này sẽ được lặp lại khoảng 100.000 lần vào các yếu tố có độ dài 2000 thành phần, tôi có thể kết thúc quan tâm đến hiệu suất là tốt.)

Trả lời

7
x = factor(c("1|1","1|0","1|1","1|1","0|0","1|1","0|1")) 
x 
# [1] 1|1 1|0 1|1 1|1 0|0 1|1 0|1 
# Levels: 0|0 0|1 1|0 1|1 

sum(unlist(lapply(strsplit(as.character(x), "|"), function(x) length(grep('0', x))))) 
# [1] 4 

hoặc

sum(nchar(gsub("[1 |]", '', x))) 
# [1] 4 

Dựa trên Comment @ Rich Scriven của

sum(nchar(gsub("[^0]", '', x))) 
# [1] 4 

Dựa trên nhận xét của @ thelatemail - sử dụng tabulate hoạt động nhanh hơn nhiều so với giải pháp trên. Đây là so sánh.

sum(nchar(gsub("[^0]", "", levels(x))) * tabulate(x)) 

Time hồ sơ:

x2 <- sample(x,1e7,replace=TRUE) 
system.time(sum(nchar(gsub("[^0]", '', x2)))); 
# user system elapsed 
# 14.24 0.22 14.65 
system.time(sum(nchar(gsub("[^0]", "", levels(x2))) * tabulate(x2))); 
# user system elapsed 
# 0.04 0.00 0.04 
system.time(sum(str_count(x2, fixed("0")))) 
# user system elapsed 
# 1.02 0.13 1.25 
+4

Nếu bạn đang làm việc trên một vectơ rất lớn, bạn có thể tiết kiệm thời gian bằng cách hoạt động trên 'cấp' của' x' chỉ - 'sum (nchar (gsub (" [^ 0] "," " , cấp độ (x))) * tabulate (x)) ' – thelatemail

+0

@thelatemail thanks. Thật tuyệt vời khi biết. Nó đánh bại mọi thứ – Sathish

+1

Điều quan trọng là 'gsub' chỉ phải hoạt động trên' length (levels (x)) 'thay vì' length (x) '- regex là khá chuyên sâu trong trường hợp này. Có nói tất cả điều đó, nó vẫn còn khá nhanh chóng để xử lý các bản ghi 10M trong <15 giây. – thelatemail

6

Dưới đây là ba tùy chọn.

Lựa chọn 1:scan() vector sử dụng sep="|"

sum(scan(text=as.character(x), sep="|") == 0) 
# [1] 4 

Phương án 2: Một nhân vật cố định trong gregexpr()

sum(unlist(gregexpr("0", x, fixed=TRUE)) > 0) 
# [1] 4 

Lựa chọn 3: Một lựa chọn rất đơn giản và đóng gói nhanh với stringr

library(stringr) 
sum(str_count(x, fixed("0"))) 
# [1] 4 
+0

Thời gian - 'set.seed (1); x2 <- mẫu (x, 1e7, thay thế = TRUE); system.time (sum (nchar (gsub ("[^ 0]", '', x2)))); system.time (sum (nchar (gsub ("[^ 0]", "", các cấp (x2))) * tabulate (x2))); system.time (sum (str_count (x2, fixed ("0")))) ' – thelatemail

+1

@thelatemail - Đó là' cấp' + 'tabulate' một là mơ mộng –

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