2013-01-21 35 views
10

Trong khi thử nghiệm với aggregate cho một câu hỏi khác here, tôi đã gặp phải một kết quả khá lạ. Tôi không thể tìm ra lý do tại sao và tôi tự hỏi nếu những gì tôi đang làm là hoàn toàn sai.kết quả không mong muốn từ tổng hợp

Giả sử, tôi có một data.frame như thế này:

df <- structure(list(V1 = c(1L, 2L, 1L, 2L, 3L, 1L), 
        V2 = c(2L, 3L, 2L, 3L, 4L, 2L), 
        V3 = c(3L, 4L, 3L, 4L, 5L, 3L), 
        V4 = c(4L, 5L, 4L, 5L, 6L, 4L)), 
        .Names = c("V1", "V2", "V3", "V4"), 
     row.names = c(NA, -6L), class = "data.frame") 
> df 
# V1 V2 V3 V4 
# 1 1 2 3 4 
# 2 2 3 4 5 
# 3 1 2 3 4 
# 4 2 3 4 5 
# 5 3 4 5 6 
# 6 1 2 3 4 

Bây giờ, nếu tôi muốn ra một data.frame với hàng độc đáo với một cột bổ sung cho thấy tần số của họ trong df. Trong ví dụ này,

# V1 V2 V3 V4 x 
# 1 1 2 3 4 3 
# 2 2 3 4 5 2 
# 3 3 4 5 6 1 

tôi đắc đầu ra này bằng aggregate bằng cách thử nghiệm như sau:

> aggregate(do.call(paste, df), by=df, print) 

# [1] "1 2 3 4" "1 2 3 4" "1 2 3 4" 
# [1] "2 3 4 5" "2 3 4 5" 
# [1] "3 4 5 6" 
# V1 V2 V3 V4       x 
# 1 1 2 3 4 1 2 3 4, 1 2 3 4, 1 2 3 4 
# 2 2 3 4 5   2 3 4 5, 2 3 4 5 
# 3 3 4 5 6     3 4 5 6 

Vì vậy, điều này đã cho tôi chuỗi dán. Vì vậy, nếu tôi sử dụng length thay vì print, nó sẽ cho tôi số lần xuất hiện như vậy, đó là kết quả mong muốn, đó là trường hợp (như được hiển thị bên dưới).

> aggregate(do.call(paste, df), by=df, length) 
# V1 V2 V3 V4 x 
# 1 1 2 3 4 3 
# 2 2 3 4 5 2 
# 3 3 4 5 6 1 

Và điều này dường như hoạt động. Tuy nhiên, khi kích thước data.frame là 4 * 2500, đầu ra data.frame là 1 * 2501 thay vì 4 * 2501 (tất cả các hàng là duy nhất, do đó tần số là 1).

> df <- as.data.frame(matrix(sample(1:3, 1e4, replace = TRUE), nrow=4)) 
> o <- aggregate(do.call(paste, df), by=df, length) 
> dim(o) 
# [1] 1 2501 

Tôi đã thử nghiệm với dữ liệu nhỏ hơn. Khung với chỉ các hàng duy nhất và nó cho đầu ra đúng (thay đổi nrow=40, ví dụ). Tuy nhiên, khi kích thước của ma trận tăng lên, điều này dường như không hoạt động. Và tôi không thể hiểu được chuyện gì đang xảy ra! Bất kỳ ý tưởng?

+2

Có thể, bởi vì chuỗi quá dài và chèn dòng lệnh 'as.character'? – Roland

+0

vâng, như là một thay thế bạn có thể làm 'tổng hợp (rep (1, nrow (df)), df, FUN = chiều dài)'. – flodel

+1

Điều này không liên quan gì đến 'as.character()' vì mỗi đối số của nó là một chiều dài 1 vectơ. Để thấy rằng phần này hoạt động, chỉ cần làm 'do.call (paste, df [1: 3,])'. –

Trả lời

10

Vấn đề ở đây là cách aggregate.data.frame() xác định nhóm.

Trong aggregate.data.frame() có một vòng lặp tạo thành biến nhóm grp. Trong vòng lặp đó, grp bị thay đổi/cập nhật thông qua:

grp <- grp * nlevels(ind) + (as.integer(ind) - 1L) 

Vấn đề với ví dụ của bạn nếu điều đó một lần by được chuyển thành các yếu tố, và vòng lặp đã đi qua tất cả những yếu tố này, trong ví dụ của bạn grp đầu lên hạnh phúc:

Browse[2]> grp 
[1] Inf Inf Inf Inf 

về cơ bản cập nhật lặp đẩy các giá trị của grp một số không thể phân biệt từ Inf.

Sau khi làm điều đó, aggregate.data.frame() sau thực hiện điều này

y <- y[match(sort(unique(grp)), grp, 0L), , drop = FALSE] 

và đây là nơi mà vấn đề trước giờ biểu lộ chính nó như là

dim(y[match(sort(unique(grp)), grp, 0L), , drop = FALSE]) 

match(sort(unique(grp)), grp, 0L) 

chỉ trả rõ ràng 1:

> match(sort(unique(grp)), grp, 0L) 
[1] 1 

vì chỉ có một giá trị duy nhất là grp.

+1

Chỉ có quá nhiều nhóm được tạo bởi 'by'. Tôi không khuyên bạn nên làm điều này nhưng một cách khác để xem vấn đề là để tạo thành các khung dữ liệu phụ tổng hợp sẽ làm việc trên nó 'grp' đã không đi đến' Inf': 'length (split (do.call) (dán, df), df)) '. ** CẢNH BÁO ** mà một số sẽ tiêu thụ tất cả RAM của bạn (trên máy tính xách tay 4GB của tôi, tôi đã nhanh chóng đập không gian hoán đổi). –

+1

@Arun yep, 'debugonce()' là bạn của bạn cho loại điều này. –

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