2009-01-14 33 views
12

Vì vậy, trước đó tôi đã trả lời câu hỏi của riêng mình về suy nghĩ trong vectơ trong R. Nhưng bây giờ tôi có một vấn đề khác mà tôi không thể 'vector hóa'. Tôi biết vectơ nhanh hơn và chậm hơn, nhưng tôi không thể tìm ra cách làm điều này theo phương pháp vector:Vectorize suy nghĩ của tôi: Hoạt động Vector trong R

Tôi có khung dữ liệu (vì lý do tình cảm mà tôi muốn gọi my.data) mà tôi muốn để thực hiện phân tích cận biên đầy đủ. Tôi cần phải loại bỏ một số yếu tố nhất định tại một thời điểm và 'giá trị' khung dữ liệu sau đó tôi cần phải làm lại lần nữa bằng cách chỉ xóa phần tử tiếp theo. Sau đó, làm lại ... và một lần nữa ... Ý tưởng là thực hiện phân tích cận biên đầy đủ trên một tập hợp con dữ liệu của tôi. Nhưng dù sao, tôi không thể quan niệm làm thế nào để làm điều này trong một cách hiệu quả vector.

Tôi đã rút ngắn một phần vòng lặp của mã xuống và nó trông giống như sau:

for (j in my.data$item[my.data$fixed==0]) { # <-- selects the items I want to loop 
              #  through 
    my.data.it <- my.data[my.data$item!= j,] # <-- this kicks item j out of the list 
    sum.data <-aggregate(my.data.it, by=list(year), FUN=sum, na.rm=TRUE) #<-- do an 
                     # aggregation 

    do(a.little.dance) && make(a.little.love) -> get.down(tonight) # <-- a little 
                    # song and dance 

    delta <- (get.love)           # <-- get some love 
    delta.list<-append(delta.list, delta, after=length(delta.list)) #<-- put my love 
                    # in a vector 
} 

Vì vậy, rõ ràng là tôi bị hack ra một loạt các công cụ ở giữa, chỉ để làm cho nó ít vụng về. Mục đích là loại bỏ vòng lặp j bằng cách sử dụng một cái gì đó hiệu quả hơn. Bất kỳ ý tưởng?

+0

@joran: Có phải là giải thưởng để chỉnh sửa câu hỏi 30 tháng tuổi. :) – Iterator

+1

một số phiên bản của necromancer, có thể? –

+0

Ý tưởng hay. Tôi đang nghĩ điều gì đó dọc theo dòng của một nhà quản lý bảo tàng lịch sử tự nhiên có thể ít bị bệnh tật hơn. Hoặc có thể là Jurassic Park? – Iterator

Trả lời

7

Dưới đây là những gì có vẻ giống như một cách R-type khác để tạo ra các khoản tiền. Tạo một vectơ miễn là vectơ đầu vào của bạn, không chứa gì ngoài tổng các phần tử n lặp lại. Sau đó, trừ vector ban đầu của bạn khỏi vectơ tổng. Kết quả: một vectơ (isums) trong đó mỗi mục là vector ban đầu của bạn trừ phần tử thứ i.

> (my.data$item[my.data$fixed==0]) 
[1] 1 1 3 5 7 
> sums <- rep(sum(my.data$item[my.data$fixed==0]),length(my.data$item[my.data$fixed==0])) 
> sums 
[1] 17 17 17 17 17 
> isums <- sums - (my.data$item[my.data$fixed==0]) 
> isums 
[1] 16 16 14 12 10 
+0

Đó là một lời nhắc nhở tốt về cách suy nghĩ theo cách r esque. Trong ứng dụng của tôi các bước sau khi tổng hợp dường như gây ra cho tôi một số vấn đề trong việc áp dụng cách tiếp cận bạn đã đề cập. Nhưng tôi đã bình chọn điều này để cung cấp cho bạn một số điểm danh tiếng. Tôi rất vui khi thấy một người R khác ở đây! –

0

Đây không phải là câu trả lời, nhưng tôi tự hỏi nếu có cái nhìn sâu sắc nằm theo hướng này:

> tapply((my.data$item[my.data$fixed==0])[-1], my.data$year[my.data$fixed==0][-1], sum) 

tapply tạo ra một bảng thống kê (số tiền, trong trường hợp này; đối số thứ ba) nhóm lại theo các thông số đưa ra là đối số thứ hai. Ví dụ:

2001 2003 2005 2007 
1 3 5 7 

Ký hiệu [-1] giảm quan sát (hàng) từ hàng đã chọn. Vì vậy, bạn có thể lặp và sử dụng [-i] trên mỗi vòng lặp

for (i in 1:length(my.data$item)) { 
    tapply((my.data$item[my.data$fixed==0])[-i], my.data$year[my.data$fixed==0][-i], sum) 
} 

ghi nhớ rằng nếu bạn có bất kỳ năm với chỉ 1 quan sát, sau đó các bảng trả về bởi các cuộc gọi tapply liên tiếp sẽ không có cùng số cột. (tức là, nếu bạn loại bỏ quan sát duy nhất cho năm 2001, thì 2003, 2005 và 2007 sẽ chỉ là các cột được trả về).

8

Kỳ lạ, học cách vector hóa trong R là điều giúp tôi làm quen với lập trình hàm cơ bản. Một kỹ thuật cơ bản sẽ được xác định hoạt động của bạn bên trong vòng lặp như một chức năng:

data = ...; 
items = ...; 

leave_one_out = function(i) { 
    data1 = data[items != i]; 
    delta = ...; # some operation on data1 
    return delta; 
} 


for (j in items) { 
    delta.list = cbind(delta.list, leave_one_out(j)); 
} 

Để vectorize, tất cả các bạn làm là thay thế các for vòng lặp với chức năng lập bản đồ sapply:

delta.list = sapply(items, leave_one_out); 
Các vấn đề liên quan