2012-01-19 34 views
6

Tôi đã viết các chức năng sau đây dựa trên subset(), mà tôi tìm thấy tiện dụng:tập con() của một vector trong R

ss <- function (x, subset, ...) 
{ 
    r <- eval(substitute(subset), data.frame(.=x), parent.frame()) 
    if (!is.logical(r)) 
     stop("'subset' must be logical") 
    x[r & !is.na(r)] 
} 

Vì vậy, tôi có thể viết:

ss(myDataFrame$MyVariableName, 500 < . & . < 1500) 

thay vì

myDataFrame$MyVariableName[ 500 < myDataFrame$MyVariableName 
           & myDataFrame$MyVariableName < 1500] 

Điều này có vẻ như điều gì đó mà những người khác có thể đã phát triển các giải pháp, mặc dù - bao gồm nội dung nào đó trong RI lõi có thể đã bỏ lỡ. Có gì ngoài kia không?

+0

Nó vẫn dường như có tác dụng nếu chúng ta thay đổi '' data.frame cho 'danh sách' và tôi nghi ngờ hiệu suất sẽ được cải thiện (= x.) . –

+0

Điểm tốt @DWin. –

+0

Để làm rõ - Tôi vừa sử dụng 'myDataFrame $ MyVariableName' làm ví dụ về tên vectơ rất dài. Tôi có lẽ nên đã sử dụng 'myVeryVeryVeryLongVariableName' hoặc một cái gì đó, nhưng nếu tôi chỉnh sửa nó ngay bây giờ, câu trả lời @ joran sẽ không có ý nghĩa nhiều. =) –

Trả lời

2

Cảm ơn bạn đã chia sẻ Ken.

Bạn có thể sử dụng:

x <- myDataFrame$MyVariableName; x[x > 100 & x < 180] 

Yours có thể yêu cầu ít gõ nhưng mã là ít khái quát hóa cho người khác nếu bạn đang chia sẻ mã. Tôi có một vài chức năng tiết kiệm thời gian giống như vậy nhưng sử dụng chúng một cách tiết kiệm vì chúng có thể làm chậm mã của bạn (các bước bổ sung) và yêu cầu bạn cũng bao gồm mã đó cho hàm đó khi bạn chia sẻ tệp với người khác.

So sánh độ dài của văn bản. Gần như giống nhau chiều dài:

ss(mtcars$hp, 100 < . & . < 180) 
x <- mtcars$hp; x[x > 100 & x < 180] 

Hãy so sánh thời gian trên 1000 lần nhắc lại.

library(rbenchmark) 
benchmark(
     tyler = x[x > 100 & x < 180], 
     ken = ss(mtcars$hp, 100 <. & . < 180), 
replications=1000) 

    test replications elapsed relative user.self sys.self user.child sys.child 
2 ken   1000 0.56 18.66667  0.36  0.03   NA  NA 
1 tyler   1000 0.03 1.00000  0.03  0.00   NA  NA 

Vì vậy, tôi đoán nó phụ thuộc vào việc bạn cần tốc độ và/hoặc khả năng chia sẻ so với tiện lợi. Nếu nó chỉ dành cho bạn trên một tập dữ liệu nhỏ tôi sẽ nói nó có giá trị.

EDIT: ĐIỂM CHUẨN MỚI

> benchmark(
+  tyler = {x <- mtcars$hp; x[x > 100 & x < 180]}, 
+  ken = ss(mtcars$hp, 100 <. & . < 180), 
+  ken2 = ss2(mtcars$hp, 100 <. & . < 180), 
+  joran = with(mtcars,hp[hp>100 & hp< 180 ]), 
+ replications=10000) 

    test replications elapsed relative user.self sys.self user.child sys.child 
4 joran  10000 0.83 2.677419  0.69  0.00   NA  NA 
2 ken  10000 3.79 12.225806  3.45  0.02   NA  NA 
3 ken2  10000 0.67 2.161290  0.35  0.00   NA  NA 
1 tyler  10000 0.31 1.000000  0.20  0.00   NA  NA 
+0

Vâng, tôi cũng nghĩ về điều đó - về cơ bản những gì tôi đang làm bên trong hàm 'ss()' của tôi, tất nhiên, nhưng 'x' của tôi được đặt tên là' .'. –

+0

Về tốc độ, tôi đã đưa ra đề xuất của @ DWin và thấy khoảng 10 lần cải thiện điểm chuẩn này. 'benchmark ( tyler = {x <- mtcars $ hp; x [x> 100 & x <180]}, ken = ss (mtcars $ hp, 100 <. &. <180), ken2 = ss2 (mtcars $ hp, 100 <. &. <180), + replications = 10000) bản sao thử nghiệm đã trôi qua user.self sys.self user.child sys.child 2 ken 10000 2,26 15.06667 2,25 0 NA NA 3 ken2 10000 0,24 1.60000 0,25 0 NA NA 1 tyler 10000 0,15 1.00000 0,15 0 NA NA' –

+0

gah, điều đó hoàn toàn không đẹp chút nào! –

4

Tôi nhận ra rằng giải pháp Ken cung cấp là tổng quát hơn hơn là chỉ chọn các mục bên trong dãy (vì nó sẽ làm việc trên bất kỳ biểu thức logic) nhưng điều này đã nhắc nhở tôi rằng Greg tuyết có nhà khai thác ghi vào so sánh trong gói Dạy Demo của mình: (. = x)

library(TeachingDemos) 
x0 <- rnorm(100) 
x0[ 0 %<% x0 %<% 1.5 ] 
+0

Tuyệt! Tôi luôn muốn có cấu trúc 'x

+0

Tôi nhớ khi Perl có một thứ như vậy - họ nhận ra rằng họ đã có một lỗi nghiêm trọng nói rằng "Bạn đã sử dụng 'x

+0

Lưu ý rằng 'a James

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