2013-03-05 12 views
13

Có thể bao gồm hai hàm trong một câu lệnh tapply hoặc tổng hợp duy nhất không?Nhiều chức năng trong một tuyên bố tapply hoặc tổng hợp đơn lẻ

Dưới đây tôi sử dụng hai câu lệnh tapply và hai câu lệnh tổng hợp: một cho giá trị trung bình và một cho SD.
Tôi muốn kết hợp các câu lệnh.

my.Data = read.table(text = " 
    animal age  sex weight 
     1 adult female  100 
     2 young male  75 
     3 adult male  90 
     4 adult female  95 
     5 young female  80 
", sep = "", header = TRUE) 

with(my.Data, tapply(weight, list(age, sex), function(x) {mean(x)})) 
with(my.Data, tapply(weight, list(age, sex), function(x) {sd(x) })) 

with(my.Data, aggregate(weight ~ age + sex, FUN = mean) 
with(my.Data, aggregate(weight ~ age + sex, FUN = sd) 

# this does not work: 

with(my.Data, tapply(weight, list(age, sex), function(x) {mean(x) ; sd(x)})) 

# I would also prefer that the output be formatted something similar to that 
# show below. `aggregate` formats the output perfectly. I just cannot figure 
# out how to implement two functions in one statement. 

    age sex mean  sd 
adult female 97.5 3.535534 
adult male  90  NA 
young female 80.0  NA 
young male  75  NA 

Tôi luôn có thể chạy hai câu lệnh riêng biệt và hợp nhất đầu ra. Tôi chỉ hy vọng có thể có một giải pháp thuận tiện hơn một chút.

Tôi tìm thấy câu trả lời dưới đây được đăng ở đây: Apply multiple functions to column using tapply

f <- function(x) c(mean(x), sd(x)) 
do.call(rbind, with(my.Data, tapply(weight, list(age, sex), f))) 

Tuy nhiên, không phải các hàng hoặc cột được dán nhãn.

 [,1]  [,2] 
[1,] 97.5 3.535534 
[2,] 80.0  NA 
[3,] 90.0  NA 
[4,] 75.0  NA 

Tôi thích giải pháp trong cơ sở R. Một giải pháp từ gói plyr đã được đăng tại liên kết ở trên. Nếu tôi có thể thêm các tiêu đề hàng và cột chính xác vào đầu ra ở trên, nó sẽ là hoàn hảo.

Trả lời

14

Nhưng những nên có:

with(my.Data, aggregate(weight, list(age, sex), function(x) { c(MEAN=mean(x), SD=sd(x))})) 

with(my.Data, tapply(weight, list(age, sex), function(x) { c(mean(x) , sd(x))})) 
# Not a nice structure but the results are in there 

with(my.Data, aggregate(weight ~ age + sex, FUN = function(x) c(SD = sd(x), MN= mean(x)))) 
    age sex weight.SD weight.MN 
1 adult female 3.535534 97.500000 
2 young female  NA 80.000000 
3 adult male  NA 90.000000 
4 young male  NA 75. 

Nguyên tắc phải được tôn trọng là phải có chức năng lợi nhuận của bạn "một điều" mà có thể hoặc là một vector hoặc một danh sách nhưng không thể là gọi liên tiếp của hai chức năng cuộc gọi.

+0

Cảm ơn bạn! Hai báo cáo tổng hợp hoạt động. Tuyên bố tapply dường như không hoạt động, nhưng tôi có thể sử dụng cách tiếp cận tổng hợp. –

+1

Vâng, tôi nghĩ rằng nó "hoạt động", chỉ cần không cung cấp cho bạn một cái gì đó mà in độc đáo. Hãy thử 'với (my.Data, tapply (trọng số, danh sách (tuổi, giới tính), hàm (x) {c (trung bình (x), sd (x))})) [1,1]' và chơi với các chỉ số để xem bên trong ma trận danh sách đó. –

+0

Tôi hiểu. Cảm ơn bạn. Và nếu tôi đặt toàn bộ câu lệnh bên trong colnames() hoặc rownames() thì tôi sẽ nhận được các nhãn. –

8

Nếu bạn muốn sử dụng data.table, nó có withby xây dựng ngay vào nó:

library(data.table) 
myDT <- data.table(my.Data, key="animal") 


myDT[, c("mean", "sd") := list(mean(weight), sd(weight)), by=list(age, sex)] 


myDT[, list(mean_Aggr=sum(mean(weight)), sd_Aggr=sum(sd(weight))), by=list(age, sex)] 
    age sex mean_Aggr sd_Aggr 
1: adult female  96.0 3.6055513 
2: young male  76.5 2.1213203 
3: adult male  91.0 1.4142136 
4: young female  84.5 0.7071068 

tôi đã sử dụng một dữ liệu hơi khác nhau thiết lập để không có NA giá trị cho sd

4

Định hình lại cho phép bạn chuyển 2 chức năng; reshape2 không.

library(reshape) 
my.Data = read.table(text = " 
    animal age  sex weight 
     1 adult female  100 
     2 young male  75 
     3 adult male  90 
     4 adult female  95 
     5 young female  80 
", sep = "", header = TRUE) 
my.Data[,1]<- NULL 
(a1<- melt(my.Data, id=c("age", "sex"), measured=c("weight"))) 
(cast(a1, age + sex ~ variable, c(mean, sd), fill=NA)) 

#  age sex weight_mean weight_sd 
# 1 adult female  97.5 3.535534 
# 2 adult male  90.0  NA 
# 3 young female  80.0  NA 
# 4 young male  75.0  NA 

Tôi nợ điều này để @Ramnath, người đã ghi nhận this vừa hôm qua.

6

Với tinh thần chia sẻ, nếu bạn đã quen với SQL, bạn cũng có thể xem xét gói "sqldf". (Nhấn mạnh thêm bởi vì bạn cần phải biết, ví dụ, rằng meanavg để có được kết quả mong muốn.)

sqldf("select age, sex, 
     avg(weight) `Wt.Mean`, 
     stdev(weight) `Wt.SD` 
     from `my.Data` 
     group by age, sex") 
    age sex Wt.Mean Wt.SD 
1 adult female 97.5 3.535534 
2 adult male 90.0 0.000000 
3 young female 80.0 0.000000 
4 young male 75.0 0.000000 
Các vấn đề liên quan