2011-09-16 30 views
32

Nói rằng tôi có một đối tượng data.frame:số Tính của các quan sát/hàng cho mỗi nhóm và thêm kết quả vào khung dữ liệu

df <- data.frame(name=c('black','black','black','red','red'), 
       type=c('chair','chair','sofa','sofa','plate'), 
       num=c(4,5,12,4,3)) 

Bây giờ tôi muốn đếm số lượng các quan sát cho mỗi sự kết hợp của nametype. Điều này có thể được thực hiện như vậy:

table(df[ , c("name","type")]) 

hoặc có thể với plyr, (mặc dù tôi không chắc chắn như thế nào).

Tuy nhiên, làm cách nào để có được kết quả được tích hợp vào khung dữ liệu gốc? Để kết quả trông như sau:

df 
# name type num count 
# 1 black chair 4  2 
# 2 black chair 5  2 
# 3 black sofa 12  1 
# 4 red sofa 4  1 
# 5 red plate 3  1 

nơi lưu trữ kết quả từ tập hợp.

Một giải pháp với plyr có thể là thú vị để tìm hiểu càng tốt, mặc dù tôi muốn thấy cách này được thực hiện với R. cơ sở

Trả lời

1

Một cách khác mà g eneralizes hơn:

df$count <- unsplit(lapply(split(df, df[c("name","type")]), nrow), df[c("name","type")]) 
+6

Vui lòng giải thích cách điều này tổng quát hơn? – smci

7

Bạn có thể làm điều này:

> ddply(df,.(name,type),transform,count = NROW(piece)) 
    name type num count 
1 black chair 4  2 
2 black chair 5  2 
3 black sofa 12  1 
4 red plate 3  1 
5 red sofa 4  1 

hoặc có lẽ bằng trực giác hơn ,

> ddply(df,.(name,type),transform,count = length(num)) 
    name type num count 
1 black chair 4  2 
2 black chair 5  2 
3 black sofa 12  1 
4 red plate 3  1 
5 red sofa 4  1 
23

Bạn có thể sử dụng ave:

df$count <- ave(df$num, df[,c("name","type")], FUN=length) 
50

Sử dụng plyr:

plyr::ddply(df, .(name, type), transform, count = length(num)) 

Sử dụng data.table:

library(data.table) 
dt = data.table(df) 
# using setkey or setkeyv to set the key 
setkeyv(dt, c('name', 'type')) 
# self 
dt[dt[ , count = length(num), 'name, type']] 

EDIT (mnel)

Sử dụng phiên bản data.table 1.8.2 hoặc cao hơn có := theo nhóm. Ngoài ra còn có giá trị .N (giới thiệu phiên bản 1.6.2), đó là số lượng hàng trong nhóm), vì vậy nó dễ dàng như

dt[ , count := .N, by = list(name, type)] 

Sử dụng dplyr:

library(dplyr) 
df %>% 
    group_by(name, type) %>% 
    mutate(count = n()) 

với phiên bản mới của dplyr (0.6.0)

df %>% 
    add_count(name, type) 
+0

Bạn có cần "setkeyv (dt, c ('Tên', 'type')) "? – skan

2

Các cơ sở R chức năng aggregate sẽ nhận được đếm với một lớp lót, nhưng thêm những tội trở lại với bản gốc data.frame dường như mất một chút thời xử lý.

df <- data.frame(name=c('black','black','black','red','red'), 
       type=c('chair','chair','sofa','sofa','plate'), 
       num=c(4,5,12,4,3)) 
df 
# name type num 
# 1 black chair 4 
# 2 black chair 5 
# 3 black sofa 12 
# 4 red sofa 4 
# 5 red plate 3 

rows.per.group <- aggregate(rep(1, length(paste0(df$name, df$type))), 
          by=list(df$name, df$type), sum) 
rows.per.group 
# Group.1 Group.2 x 
# 1 black chair 2 
# 2  red plate 1 
# 3 black sofa 1 
# 4  red sofa 1 

my.summary <- do.call(data.frame, rows.per.group) 
colnames(my.summary) <- c(colnames(df)[1:2], 'rows.per.group') 
my.data <- merge(df, my.summary, by = c(colnames(df)[1:2])) 
my.data 
# name type num rows.per.group 
# 1 black chair 4    2 
# 2 black chair 5    2 
# 3 black sofa 12    1 
# 4 red plate 3    1 
# 5 red sofa 4    1 
3

này nên làm công việc của bạn:

df_agg <- aggregate(num~name+type,df,FUN=NROW) names(df_agg)[3] <- "count" df <- merge(df,df_agg,by=c('name','type'),all.x=TRUE)

0

Một hai dòng khác là để tạo ra một biến 0s và sau đó điền vào nó với split<-, splitlengths như thế này:

# generate vector of 0s 
df$count <-0L 

# fill it in 
split(df$count, df[c("name", "type")]) <- lengths(split(df$num, df[c("name", "type")])) 

Điều này trả về kết quả mong muốn

df 
    name type num count 
1 black chair 4  2 
2 black chair 5  2 
3 black sofa 12  1 
4 red sofa 4  1 
5 red plate 3  1 

Về cơ bản, RHS tính toán độ dài của từng kết hợp loại tên, trả về một vector có tên có độ dài 6 với 0 cho "red.chair" và "black.plate". Điều này được cung cấp cho LHS với split <- lấy vector và thêm một cách thích hợp các giá trị trong các vị trí đã cho của chúng. Đây thực chất là gì ave không, như bạn có thể thấy rằng thứ hai đến dòng cuối cùng của ave

split(x, g) <- lapply(split(x, g), FUN) 

Tuy nhiên, lengths là một phiên bản tối ưu hóa của sapply(list, length).

0

Bạn chỉ còn một bước nữa là kết hợp số hàng vào bộ dữ liệu cơ sở.

Sử dụng tidy() chức năng từ gói broom, chuyển đổi bảng tần số vào một khung dữ liệu và bên tham gia với df:

df <- data.frame(name=c('black','black','black','red','red'), 
         type=c('chair','chair','sofa','sofa','plate'), 
         num=c(4,5,12,4,3)) 
library(broom) 
df <- merge(df, tidy(table(df[ , c("name","type")])), by=c("name","type")) 
df 
    name type num Freq 
1 black chair 4 2 
2 black chair 5 2 
3 black sofa 12 1 
4 red plate 3 1 
5 red sofa 4 1 
Các vấn đề liên quan