2011-08-29 42 views
8

tôi sử dụng đoạn mã sau để tóm tắt dữ liệu của tôi, nhóm lại theo Compound, Replicate và Mass.Làm thế nào để ddply() mà không cần phân loại?

summaryDataFrame <- ddply(reviewDataFrame, .(Compound, Replicate, Mass), 
    .fun = calculate_T60_Over_T0_Ratio) 

Một tác dụng phụ đáng tiếc là các khung dữ liệu kết quả được sắp xếp theo các lĩnh vực này. Tôi muốn làm điều này và giữ Compound, Replicate và Mass theo thứ tự giống như trong khung dữ liệu gốc. Bất kỳ ý tưởng? Tôi đã thử thêm một cột "Sắp xếp" các số nguyên tuần tự vào dữ liệu gốc, nhưng tất nhiên tôi không thể bao gồm số đó trong các biến. Vì tôi không muốn 'nhóm theo', và do đó nó không được trả về trong summaryDataFrame.

Cảm ơn sự giúp đỡ.

+0

Điều này không liên quan gì đến 'write.table'; tiêu đề phải được thay đổi. –

Trả lời

11

này đã đưa ra trong danh sách plyr gửi thư một khi trở lại (nêu ra bởi @kohske không kém) và điều này là một giải pháp được cung cấp bởi Peter Meilstrup đối với trường hợp có giới hạn:

#Peter's version used a function gensym to 
# create the col name, but I couldn't track down 
# what package it was in. 
keeping.order <- function(data, fn, ...) { 
    col <- ".sortColumn" 
    data[,col] <- 1:nrow(data) 
    out <- fn(data, ...) 
    if (!col %in% colnames(out)) stop("Ordering column not preserved by function") 
    out <- out[order(out[,col]),] 
    out[,col] <- NULL 
    out 
} 

#Some sample data 
d <- structure(list(g = c(2L, 2L, 1L, 1L, 2L, 2L), v = c(-1.90127112738315, 
-1.20862680183042, -1.13913266070505, 0.14899803094742, -0.69427656843677, 
0.872558638137971)), .Names = c("g", "v"), row.names = c(NA, 
-6L), class = "data.frame") 

#This one resorts 
ddply(d, .(g), mutate, v=scale(v)) #does not preserve order of d 

#This one does not 
keeping.order(d, ddply, .(g), mutate, v=scale(v)) #preserves order of d 

Xin đừng đọc thread cho Hadley lưu ý về lý do tại sao chức năng này có thể không đủ chung để cuộn vào ddply, đặc biệt vì chức năng này có thể áp dụng trong trường hợp của bạn vì bạn có khả năng trả về ít hàng hơn với mỗi phần.

Edited để bao gồm một chiến lược đối với trường hợp tổng quát hơn

Nếu ddply được xuất ra cái gì mà được sắp xếp theo một thứ tự mà bạn không thích, bạn có hai lựa chọn: xác định thứ tự mong muốn trên các biến tách trước sử dụng các yếu tố được sắp xếp hoặc tự sắp xếp đầu ra sau khi thực tế.

Ví dụ, hãy xem xét các dữ liệu sau:

d <- data.frame(x1 = rep(letters[1:3],each = 5), 
       x2 = rep(letters[4:6],5), 
       x3 = 1:15,stringsAsFactors = FALSE) 

sử dụng chuỗi, cho bây giờ. ddply sẽ sắp xếp các đầu ra, mà trong trường hợp này sẽ kéo theo mặc định đặt hàng từ vựng:

> ddply(d,.(x1,x2),summarise, val = sum(x3)) 
    x1 x2 val 
1 a d 5 
2 a e 7 
3 a f 3 
4 b d 17 
5 b e 8 
6 b f 15 
7 c d 13 
8 c e 25 
9 c f 27 


> ddply(d[sample(1:15,15),],.(x1,x2),summarise, val = sum(x3)) 
    x1 x2 val 
1 a d 5 
2 a e 7 
3 a f 3 
4 b d 17 
5 b e 8 
6 b f 15 
7 c d 13 
8 c e 25 
9 c f 27 

Nếu khung dữ liệu kết quả không được kết thúc trong "đúng" trật tự, nó có thể là vì bạn thực sự muốn có một số những biến được đặt hàng yếu tố. Giả sử chúng ta thực sự muốn x1x2 ra lệnh như vậy:

d$x1 <- factor(d$x1, levels = c('b','a','c'),ordered = TRUE) 
d$x2 <- factor(d$x2, levels = c('d','f','e'), ordered = TRUE) 

Bây giờ khi chúng tôi sử dụng ddply, các loại kết quả sẽ được như chúng tôi dự định:

> ddply(d,.(x1,x2),summarise, val = sum(x3)) 
    x1 x2 val 
1 b d 17 
2 b f 15 
3 b e 8 
4 a d 5 
5 a f 3 
6 a e 7 
7 c d 13 
8 c f 27 
9 c e 25 

Các đạo đức của câu chuyện ở đây là nếu ddply là xuất ra một thứ gì đó theo thứ tự bạn không có ý định, đó là một dấu hiệu tốt cho thấy bạn nên sử dụng các yếu tố đặt hàng cho các biến mà bạn đang chia nhỏ.

+0

Cảm ơn. Điều này dường như làm việc cho tôi "gần như". Làm cách nào để giữ '.sortColumn' trong dữ liệu trả về của hàm của tôi? 'calculate_T60_Over_T0_Ratio <- function (df) {' '## kiểm tra để đảm bảo các điểm thời gian phù hợp đang được sử dụng cho tỷ lệ ' ' t60Value = df [which (df [, "Time"] == " t = 60 ")," Kết quả "]' 't0Value = df [trong đó (df [," Thời gian "] ==" t = 0 ")," Kết quả "]' 'if (t0Value == 0) { ' 'in ("Lỗi - Chia cho số không!")' ' trở lại ("NA") ' '} else {' 'trở lại (t60Value/t0Value)' '} ' '}' – James

+0

@James Nếu bạn muốn giữ '.sortColumn' trong kết quả, bạn có thể chỉ bỏ qua dòng' out [, col] <- NULL' từ 'keep.order'. – joran

+0

Xin lỗi, tôi không rõ. Tôi nhận được lỗi từ 'keep.order' vì' .sortColumn' không được trả về bởi hàm của tôi (xem ở trên). – James

1

Cuối cùng tôi đã thêm cột 'lập chỉ mục' vào khung dữ liệu gốc. Nó bao gồm hai cột pasted với sep="_". Sau đó, tôi tạo một khung dữ liệu khác chỉ gồm unique thành viên của cột 'lập chỉ mục' và một bộ đếm 1:length(df). Tôi đã làm ddply() trên dữ liệu trả về một khung dữ liệu được sắp xếp. Sau đó, để lấy lại thứ tự theo thứ tự ban đầu, tôi đã làm merge() khung dữ liệu kết quả và khung dữ liệu chỉ mục (đảm bảo các cột được đặt tên giống nhau làm cho việc này trở nên dễ dàng hơn). Cuối cùng, tôi đã làm order và xóa các cột không liên quan.

Không phải là giải pháp thanh lịch mà là giải pháp hiệu quả.

Cảm ơn bạn đã hỗ trợ. Nó khiến tôi suy nghĩ đúng hướng.

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