2015-03-05 24 views
33

Câu hỏi của tôi bao gồm tổng hợp các giá trị trên nhiều cột của một khung dữ liệu và tạo cột mới tương ứng với tổng kết này bằng cách sử dụng dplyr. Các mục dữ liệu trong các cột là nhị phân (0,1). Tôi đang nghĩ về một tương tự hàng khôn ngoan của hàm summarise_each hoặc mutate_each của dplyr. Dưới đây là một ví dụ tối thiểu của khung dữ liệu:Tổng trên nhiều cột với dplyr

library(dplyr) 
df=data.frame(
    x1=c(1,0,0,NA,0,1,1,NA,0,1), 
    x2=c(1,1,NA,1,1,0,NA,NA,0,1), 
    x3=c(0,1,0,1,1,0,NA,NA,0,1), 
    x4=c(1,0,NA,1,0,0,NA,0,0,1), 
    x5=c(1,1,NA,1,1,1,NA,1,0,1)) 

> df 
    x1 x2 x3 x4 x5 
1 1 1 0 1 1 
2 0 1 1 0 1 
3 0 NA 0 NA NA 
4 NA 1 1 1 1 
5 0 1 1 0 1 
6 1 0 0 0 1 
7 1 NA NA NA NA 
8 NA NA NA 0 1 
9 0 0 0 0 0 
10 1 1 1 1 1 

tôi có thể sử dụng một cái gì đó như:

df <- df %>% mutate(sumrow= x1 + x2 + x3 + x4 + x5) 

nhưng điều này sẽ liên quan đến việc viết ra tên của mỗi cột. Tôi có 50 cột. Ngoài ra, tên cột thay đổi tại các lần lặp khác nhau của vòng lặp mà tôi muốn triển khai hoạt động này vì vậy tôi muốn thử tránh phải đưa ra bất kỳ tên cột nào.

Tôi làm cách nào hiệu quả nhất? Bất kỳ hỗ trợ nào sẽ được đánh giá cao.

+7

Tại sao «dplyr'? Tại sao không chỉ đơn giản 'df $ sumrow <- rowSums (df, na.rm = TRUE)' từ cơ sở R? Hoặc '' 'df $ sumrow <- Reduce (' + ', df)' '' nếu bạn muốn sao chép chính xác điều bạn đã làm với 'dplyr'. –

+5

Bạn có thể thực hiện cả hai với 'dplyr' cũng như trong' '' df%>% mutate (sumrow = Reduce ('+',.)) '' 'Hoặc' df%>% mutate (sumrow = rowSums (.)) ' –

+0

Có, hàm R' rowSums' cơ bản hoạt động tốt. Tuy nhiên, hãy thử các đề xuất trong 'dplyr'; 'df%>% mutate (sumrow = rowSums (.))' và 'df%>% mutate (sumrow = Reduce (' + ',.))' tạo ra các lỗi. Tôi vừa nghĩ đến việc kết hợp các hoạt động trong một chuỗi dplyr cùng với các hoạt động khác trước đó và sau đó trong chuỗi .. @ DavidArenburg – amo

Trả lời

36

Làm thế nào về

sum xuống mỗi cột

df %>% 
    replace(is.na(.), 0) %>% 
    summarise_each(funs(sum)) 

sum lên mỗi hàng

df %>% 
    replace(is.na(.), 0) %>% 
    mutate(sum = rowSums(.[1:5])) 
+5

'summaryise_each' tổng dọc theo mỗi cột trong khi những gì được yêu cầu là tổng dọc theo mỗi hàng – amo

+0

Tôi đang cố gắng để đạt được cùng, nhưng DF của tôi có một cột là một nhân vật, do đó tôi không thể tổng hợp tất cả các cột. Tôi đoán tôi nên sửa đổi phần '(. [1: 5])', nhưng tiếc là tôi không quen thuộc với cú pháp cũng như tôi không biết cách tìm kiếm trợ giúp về nó. Đã thử với 'mutate (sum = rowSums (is.numeric (.)))' Nhưng không hoạt động. – ccamara

+0

Bạn cũng có thể thử thay thế tất cả các giá trị không bằng 0 bằng cách sử dụng 'replace (! Is.numeric (.), 0)%>%'? – Boern

10

Nếu bạn muốn tổng hợp các cột nhất định, tôi muốn sử dụng một cái gì đó như thế này:

library(dplyr) 
df=data.frame(
    x1=c(1,0,0,NA,0,1,1,NA,0,1), 
    x2=c(1,1,NA,1,1,0,NA,NA,0,1), 
    x3=c(0,1,0,1,1,0,NA,NA,0,1), 
    x4=c(1,0,NA,1,0,0,NA,0,0,1), 
    x5=c(1,1,NA,1,1,1,NA,1,0,1)) 
df %>% select(x3:x5) %>% rowSums(na.rm=TRUE) -> df$x3x5.total 
head(df) 

Bằng cách này bạn có thể sử dụng cú pháp của dplyr::select.

+0

Tôi thích cách tiếp cận này ở trên những người khác vì nó không yêu cầu buộc NA vào 0 –

11

Tôi sẽ sử dụng đối sánh cụm từ thông dụng để tổng hợp các biến với một số tên mẫu nhất định. Ví dụ:

df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE), 
        sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE)) 

Bằng cách này, bạn có thể tạo nhiều biến làm một nhóm biến số nhất định của khung dữ liệu.

+0

giải pháp tuyệt vời! Tôi đã tìm kiếm một hàm dplyr cụ thể làm điều này trong các bản phát hành gần đây, nhưng không tìm thấy – agenis

1

Tôi gặp sự cố này thường xuyên và cách dễ nhất để thực hiện việc này là sử dụng hàm apply() trong lệnh mutate.

library(tidyverse) 
df=data.frame(
    x1=c(1,0,0,NA,0,1,1,NA,0,1), 
    x2=c(1,1,NA,1,1,0,NA,NA,0,1), 
    x3=c(0,1,0,1,1,0,NA,NA,0,1), 
    x4=c(1,0,NA,1,0,0,NA,0,0,1), 
    x5=c(1,1,NA,1,1,1,NA,1,0,1)) 

df %>% 
    mutate(sum = select(., x1:x5) %>% apply(1, sum, na.rm=TRUE)) 

Ở đây bạn có thể sử dụng bất cứ điều gì bạn muốn chọn các cột bằng cách sử dụng tiêu chuẩn dplyr thủ thuật (ví dụ starts_with() hoặc). Bằng cách thực hiện tất cả công việc trong một lệnh mutate đơn lẻ, hành động này có thể xảy ra ở bất kỳ đâu trong một luồng xử lý dplyr. Cuối cùng, bằng cách sử dụng hàm apply(), bạn có thể linh hoạt sử dụng bất kỳ tóm tắt nào bạn cần, kể cả chức năng tóm tắt được xây dựng theo mục đích của riêng bạn.

Ngoài ra, nếu ý tưởng sử dụng chức năng không gọn gàng không hấp dẫn, thì bạn có thể tập hợp các cột, tóm tắt chúng và cuối cùng kết nối lại với khung dữ liệu gốc.

df <- df %>% mutate(id = 1:n()) # Need some ID column for this to work 

df <- df %>% 
    group_by(id) %>% 
    gather('Key', 'value', starts_with('x')) %>% 
    summarise(Key.Sum = sum(value)) %>% 
    left_join(df, .) 

Ở đây tôi sử dụng starts_with() chức năng để chọn các cột và tính tổng và bạn có thể làm bất cứ điều gì bạn muốn với NA giá trị.Nhược điểm của phương pháp này là trong khi nó là khá linh hoạt, nó không thực sự phù hợp với một dòng làm sạch dữ liệu dplyr.

+0

Có vẻ ngớ ngẩn khi sử dụng 'apply' khi đây là những gì' rowSums' được thiết kế cho. – zacdav

+0

Trong trường hợp này 'rowSums' hoạt động thực sự tốt như' rowMeans', nhưng tôi luôn cảm thấy hơi lạ khi tự hỏi "Điều gì sẽ xảy ra nếu điều tôi cần tính toán không phải là tổng hoặc nghĩa là gì?" Tuy nhiên, 99% thời gian tôi phải làm một cái gì đó như thế này, nó hoặc là một tổng hoặc có nghĩa là, do đó, có thể thêm chút linh hoạt trong việc sử dụng chức năng 'áp dụng 'chung không phải là có hại. –

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