2011-12-18 46 views
5

Tôi có một tập dữ liệu tương đối lớn (16.000 + x ~ 31). Nói cách khác, nó đủ lớn đến mức tôi không muốn thao tác nó theo từng dòng trong Excel. Dữ liệu có dạng này:Cách thêm cột đếm dựa trên giá trị trong các cột khác trong R

block site  day X1 X2 
1  1  1 0.4 5.1 
1  1  2 0.8 1.1 
1  1  3 1.1 4.2 
1  2  1 ... ... 
1  2  2 
1  2  3 
2  3  1 
2  3  2 
2  3  3 
2  4  1 
2  4  2 
2  4  3 

Như bạn có thể thấy, số lượng trang web liên tục nhưng tôi muốn một cột mà số trang web đặt lại với mỗi khối. Ví dụ, tôi muốn một cái gì đó như thế này dưới đây:

block site  day X1 X2 site2 
1  1  1 0.4 5.1 1 
1  1  2 0.8 1.1 1 
1  1  3 1.1 4.2 1 
1  2  1 ... ... 2 
1  2  2    2 
1  2  3    2 
2  3  1    1 
2  3  2    1 
2  3  3    1 
2  4  1    2 
2  4  2    2 
2  4  3    2 

Tôi đã suy nghĩ về việc sử dụng hàm R rle nhưng không chắc chắn nếu nó sẽ làm việc vì biến chứng với ngày. Nếu không, tôi sẽ thử một cái gì đó như:

Data$site2 <- sequence(rle(Data$block)$lengths) 

Có ai có đề xuất thêm số lượng cột (chuỗi) số trang trong mỗi khối không? Nếu nó giúp, có số ngày tương tự (263) được ghi lại cho mỗi trang nhưng có số lượng trang web khác nhau trên mỗi khối.

Trả lời

6

Dưới đây là một giải pháp hơi vụng về sử dụng plyrddply:

ddply(df,.(block),transform, 
        site1 = rep(1:length(unique(site)), 
          times = rle(site)$lengths)) 

Hoặc một phiên bản hơi tinh quái:

ddply(df,.(block),transform,site1 = as.integer(as.factor(site))) 

Có thể có một cách thông minh để làm điều này trực tiếp, tuy nhiên, sử dụng các chức năng khác nhau seq, sequencerle, nhưng bộ não của tôi hơi bị mờ một chút. Nếu bạn để nó mở cho một chút, một người nào đó có thể sẽ đi cùng với một giải pháp không trơn tru plyr.

+0

Cảm ơn bạn, điều này đã làm việc một cách hoàn hảo. Tôi đã nhìn thấy plyr trước nhưng không bao giờ sử dụng nó. ddply là hoàn hảo, tôi đã thực sự temped để phá vỡ các ma trận, sử dụng reshape (= rộng) vào ngày, áp dụng các rle (trang web) và sau đó cố gắng để reshape (= dài). Tôi không biết nếu nó sẽ làm việc nhưng tôi đã tìm thấy có khoảng 1000 cách dễ dàng hơn để làm điều đó. Tôi thích giải pháp dpdply. cảm ơn một lần nữa. – djhocking

+0

Đẹp nhất, chỉ cần thử các tùy chọn ddply trên một vấn đề tương tự và làm việc hoàn hảo đầu tiên thời gian – Ell

1

Sử dụng tapply có thể làm việc

# Make some fake data 
dat <- data.frame(block = rep(1:3, each = 4), site = rep(1:6, each = 2), val = rnorm(12)) 
# For each block reset the count 
dat$site2 <- unlist(tapply(dat$site, dat$block, function(x){x - min(x) + 1})) 
+0

Điều này dường như không làm việc cho dữ liệu lộn xộn của tôi. Tôi quên rằng trang web không phải là hoàn toàn liên tục bởi vì các dataloggers tại một số trang web không thành công hoặc đã bị mất tích. Vì vậy, đôi khi trong suốt số liệu trang web được bỏ qua, nhưng những gì tôi cần là một biến mà chỉ cần đếm để tôi có thể chu kỳ với lập chỉ mục trong các chức năng vòng lặp như một phần của phân tích của tôi. Có lẽ nếu tôi thử những gì bạn đề nghị nhưng với một số chức năng thông minh thêm vào giá trị trước đó trong site2 hơn là dựa trên số trang web ban đầu. – djhocking

0

Via ave:

df1 <- structure(list(block = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2), 
    site = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4), day = c(1, 
    2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)), .Names = c("block", "site", 
"day"), row.names = c("2", "3", "4", "5", "6", "7", "8", "9", 
"10", "11", "12", "13"), class = "data.frame") 

df1$site2 <- ave(df1$site,df1$block,FUN=function(x) match(x,sort(unique(x)))) 
Các vấn đề liên quan