2015-07-17 17 views
7

Tôi đang cố gắng cuộn lên một loạt các hàng trong một ngày thành một hàng. Tôi muốn nó trong dplyr nếu có thể. Tôi biết rằng mã của tôi còn xa mới đúng, nhưng điều này là thế nào đến nay tôi nhận:R cuộn hàng lên một hàng đơn (biến số liên tục và biến số)

data %>% 
    group_by(DAY) %>% 
    summarise_each(funs(Sum = n()), SEX, GROUP, TOTAL) 

gốc:

DAY SEX GROUP TOTAL  
7/1/14 FEMALE A 1  
7/1/14 FEMALE B 1  
7/1/14 FEMALE B 1  
7/1/14 FEMALE A 1  
7/1/14 MALE A 1  
7/1/14 MALE B 2  

mới:

DAY  FEMALE MALE GROUP_A GROUP_B TOTAL 
7/1/14 4  2  3  3  7 
+0

Vâng, ở cái nhìn đầu tiên, đơn giản nhất sẽ viết nó ra 'data%>% group_by (DAY)%>% tóm tắt (FEMALE = tổng (SEX ==" FEMALE "), MALE = tổng (SEX ==" MALE "), GROUP_A = sum (GROUP = = "A"), GROUP_B = tổng (GROUP == "B"), TOTAL = tổng (TOTAL)) '. Nhưng tôi đoán bạn đang phấn đấu cho sự thanh lịch mã. :-) – lukeA

Trả lời

8

Một cách khác với data.table, thử nghiệm trên một data.frame với nhiều hơn một ngày.

require(data.table) 
setDT(data)[, as.list(c(table(SEX), table(GROUP), TOTAL=sum(TOTAL))), by=DAY] 

#  DAY FEMALE MALE A B TOTAL 
#1: 7/1/14  3 0 1 2  3 
#2: 8/1/14  1 2 2 1  4 

EDIT: khác, ít sử dụng, tùy chọn (bạn không cần phải biết biến là những yếu tố và đó là số), nhờ sự giúp đỡ từ @jangorecki và @DavidArenburg

wh_num <- sapply(data, is.numeric)[-1] 
wh_fact <-sapply(data, is.factor)[-1] 
setDT(data)[, as.list(c(lapply(.SD[, wh_fact, with = FALSE], table), 
         lapply(.SD[, wh_num, with = FALSE], sum), 
         recursive = TRUE)), by = DAY] 

#  DAY SEX.FEMALE SEX.MALE GROUP.A GROUP.B TOTAL 
#1: 7/1/14   3  0  1  2  3 
#2: 8/1/14   1  2  2  1  4 

dữ liệu

data <- structure(list(DAY = c("7/1/14", "7/1/14", "7/1/14", "8/1/14", 
"8/1/14", "8/1/14"), SEX = structure(c(1L, 1L, 1L, 1L, 2L, 2L 
), .Label = c("FEMALE", "MALE"), class = "factor"), GROUP = structure(c(1L, 
2L, 2L, 1L, 1L, 2L), .Label = c("A", "B"), class = "factor"), 
    TOTAL = c(1L, 1L, 1L, 1L, 1L, 2L)), .Names = c("DAY", "SEX", 
"GROUP", "TOTAL"), row.names = c(NA, -6L), class = "data.frame") 
3

Cách bạn tính toán tổng số (tổng hợp) và các cột khác (bảng) khác nhau đáng kể, vì vậy bạn có thể phải thực hiện các bước này một cách riêng biệt. Tính toán tổng số là dễ dàng. Đối với lập bảng, tôi đề nghị sử dụng tidyr như sau:

# required packages 
require(dplyr) 
require(tidyr) 

# calculations 
data %>% 
    group_by(DAY) %>%      # group by day 
    mutate(TOTAL = sum(TOTAL)) %>%  # first calculate total 
    gather(key, value, -DAY, -TOTAL) %>% # collapse 
    unite(group, key, value) %>%   # get sensible column names 
    group_by(DAY, TOTAL) %>%    # group by day and total 
    do(as.data.frame(table(.$group))) %>% # table 
    spread(Var1, Freq)     # spread out 

##  DAY TOTAL GROUP_A GROUP_B SEX_FEMALE SEX_MALE 
## 1 7/1/14  7  3  3   4  2 
+1

Tôi thực sự ngạc nhiên khi bạn ưa thích giải pháp này phức tạp hơn 'dplyr/tidyr' trên một giải pháp 'data.table' đơn giản mà bạn đã đăng nhiều lần trước đây. –

+0

@DavidArenburg: Tôi thường cố gắng trả lời các gói mà OP có vẻ thích. Nhưng tôi đồng ý rằng trong trường hợp này giải pháp data.table là thích hợp hơn (và tôi đã upvoted nó). – shadow

5

Nó có vẻ hơi phức tạp, nhưng đây là một câu thần chú ngắn

dat %>% group_by(DAY) %>% 
    summarise_each(funs(ifelse(is.numeric(.), sum(.), list(table(.))))) -> res 

data.frame(DAY=res$DAY, t(unlist(res[, 2:ncol(res)]))) 
#  DAY SEX.FEMALE SEX.MALE GROUP.A GROUP.B TOTAL 
# 1 7/1/14   4  2  3  3  7 

Ở đây, bạn chỉ cần tóm tắt mỗi cột như một bảng nếu nó không phải là số, hoặc tổng hợp nếu nó là (cho tổng cột). Điều này cần được trả về dưới dạng danh sách kể từ khi summarise_each mong đợi một giá trị duy nhất. Sau đó, kết quả được mở rộng đến một số data.frame thông thường.

+1

Tôi không chắc chắn rằng nó hoạt động chính xác cho một số ngày mặc dù. Ví dụ: nếu bạn sẽ thay đổi 3 ngày cuối cùng thành '8/1/14'. –

+0

@DavidArenburg yea, đó là trường hợp đặc biệt của một hàng duy nhất. Bạn có thể làm cho nó hoạt động nhiều hơn, một cái gì đó dọc theo dòng của unlist và rbind các hàng với nhau tôi đoán. – jenesaisquoi

+0

Tôi nghi ngờ @ user2434624 chỉ có một ngày trong dữ liệu gốc ... – Cath

3

Một cách tiếp cận có thể:

library(reshape2) 
library(data.table) 

cbind(dcast(df, DAY~SEX), 
     dcast(df, DAY~GROUP)[-1], 
     setDT(df)[,.(total=sum(TOTAL)),DAY][,-1,with=F]) 

#  DAY FEMALE MALE A B total 
#1 7/1/14  4 2 3 3  7 
Các vấn đề liên quan