R data.table:子组加权百分比
R data.table: subgroup weighted percent of group
我有一个 data.table
喜欢:
library(data.table)
widgets <- data.table(serial_no=1:100,
color=rep_len(c("red","green","blue","black"),length.out=100),
style=rep_len(c("round","pointy","flat"),length.out=100),
weight=rep_len(1:5,length.out=100) )
虽然我不确定这是最 data.table
的方式,但我可以使用 table
和 length
一步计算分组频率——例如,回答问题 "What percent of red widgets are round?"
编辑:此代码未提供正确答案
# example A
widgets[, list(style = unique(style),
style_pct_of_color_by_count =
as.numeric(table(style)/length(style)) ), by=color]
# color style style_pct_of_color_by_count
# 1: red round 0.32
# 2: red pointy 0.32
# 3: red flat 0.36
# 4: green pointy 0.32
# ...
但是我不能用那种方法来回答像"By weight, what percent of red widgets are round?"这样的问题我只能想出一个两步法:
# example B
widgets[,list(cs_weight=sum(weight)),by=list(color,style)][,list(style, style_pct_of_color_by_weight=cs_weight/sum(cs_weight)),by=color]
# color style style_pct_of_color_by_weight
# 1: red round 0.3466667
# 2: red pointy 0.3466667
# 3: red flat 0.3066667
# 4: green pointy 0.3333333
# ...
我正在寻找 B 的单步方法,如果可以改进的话,A 的解释加深了我对按组操作的 data.table
语法的理解。请注意,此问题与 Weighted sum of variables by groups with data.table 不同,因为我的问题涉及子组并避免了多个步骤。 TYVM.
这几乎是一步:
# A
widgets[,{
totwt = .N
.SD[,.(frac=.N/totwt),by=style]
},by=color]
# color style frac
# 1: red round 0.36
# 2: red pointy 0.32
# 3: red flat 0.32
# 4: green pointy 0.36
# 5: green flat 0.32
# 6: green round 0.32
# 7: blue flat 0.36
# 8: blue round 0.32
# 9: blue pointy 0.32
# 10: black round 0.36
# 11: black pointy 0.32
# 12: black flat 0.32
# B
widgets[,{
totwt = sum(weight)
.SD[,.(frac=sum(weight)/totwt),by=style]
},by=color]
# color style frac
# 1: red round 0.3466667
# 2: red pointy 0.3466667
# 3: red flat 0.3066667
# 4: green pointy 0.3333333
# 5: green flat 0.3200000
# 6: green round 0.3466667
# 7: blue flat 0.3866667
# 8: blue round 0.2933333
# 9: blue pointy 0.3200000
# 10: black round 0.3733333
# 11: black pointy 0.3333333
# 12: black flat 0.2933333
工作原理:在进入更精细的组(color
和 style
) 制表。
备选方案。如果 style
在每个 color
中重复并且这仅用于显示目的,请尝试 table
:
# A
widgets[,
prop.table(table(color,style),1)
]
# style
# color flat pointy round
# black 0.32 0.32 0.36
# blue 0.36 0.32 0.32
# green 0.32 0.36 0.32
# red 0.32 0.32 0.36
# B
widgets[,rep(1L,sum(weight)),by=.(color,style)][,
prop.table(table(color,style),1)
]
# style
# color flat pointy round
# black 0.2933333 0.3333333 0.3733333
# blue 0.3866667 0.3200000 0.2933333
# green 0.3200000 0.3333333 0.3466667
# red 0.3066667 0.3466667 0.3466667
对于 B,这会扩展数据,以便每个重量单位都有一个观测值。对于大数据,这样的扩展将不是一个好主意(因为它会花费太多内存)。此外,weight
必须是整数;否则,它的总和将被默默地截断为 1(例如,尝试 rep(1,2.5) # [1] 1 1
)。
使用 dplyr
可能是个好主意
df <- widgets %>%
group_by(color, style) %>%
summarise(count = n()) %>%
mutate(freq = count/sum(count))
df2 <- widgets %>%
group_by(color, style) %>%
summarise(count_w = sum(weight)) %>%
mutate(freq = count_w/sum(count_w))
为 color
中的每个 style
计算频率 table,然后为每一行查找 table 中该行的 style
的频率最后除以 color
中的行数。
widgets[, frac := table(style)[style] / .N, by = color]
给予:
> widgets
serial_no color style weight frac
1: 1 red round 1 0.36
2: 2 green pointy 2 0.36
3: 3 blue flat 3 0.36
4: 4 black round 4 0.36
5: 5 red pointy 5 0.32
6: 6 green flat 1 0.32
7: 7 blue round 2 0.32
8: 8 black pointy 3 0.32
9: 9 red flat 4 0.32
10: 10 green round 5 0.32
... etc ...
如果需要,这可以很容易地转换为 base 或 dplyr:
# base
prop <- function(x) table(x)[x] / length(x)
transform(widgets, frac = ave(style, color, FUN = prop))
# dplyr - uses prop function from above
library(dplyr)
widgets %>% group_by(color) %>% mutate(frac = prop(style)) %>% ungroup
我有一个 data.table
喜欢:
library(data.table)
widgets <- data.table(serial_no=1:100,
color=rep_len(c("red","green","blue","black"),length.out=100),
style=rep_len(c("round","pointy","flat"),length.out=100),
weight=rep_len(1:5,length.out=100) )
虽然我不确定这是最 data.table
的方式,但我可以使用 table
和 length
一步计算分组频率——例如,回答问题 "What percent of red widgets are round?"
编辑:此代码未提供正确答案
# example A
widgets[, list(style = unique(style),
style_pct_of_color_by_count =
as.numeric(table(style)/length(style)) ), by=color]
# color style style_pct_of_color_by_count
# 1: red round 0.32
# 2: red pointy 0.32
# 3: red flat 0.36
# 4: green pointy 0.32
# ...
但是我不能用那种方法来回答像"By weight, what percent of red widgets are round?"这样的问题我只能想出一个两步法:
# example B
widgets[,list(cs_weight=sum(weight)),by=list(color,style)][,list(style, style_pct_of_color_by_weight=cs_weight/sum(cs_weight)),by=color]
# color style style_pct_of_color_by_weight
# 1: red round 0.3466667
# 2: red pointy 0.3466667
# 3: red flat 0.3066667
# 4: green pointy 0.3333333
# ...
我正在寻找 B 的单步方法,如果可以改进的话,A 的解释加深了我对按组操作的 data.table
语法的理解。请注意,此问题与 Weighted sum of variables by groups with data.table 不同,因为我的问题涉及子组并避免了多个步骤。 TYVM.
这几乎是一步:
# A
widgets[,{
totwt = .N
.SD[,.(frac=.N/totwt),by=style]
},by=color]
# color style frac
# 1: red round 0.36
# 2: red pointy 0.32
# 3: red flat 0.32
# 4: green pointy 0.36
# 5: green flat 0.32
# 6: green round 0.32
# 7: blue flat 0.36
# 8: blue round 0.32
# 9: blue pointy 0.32
# 10: black round 0.36
# 11: black pointy 0.32
# 12: black flat 0.32
# B
widgets[,{
totwt = sum(weight)
.SD[,.(frac=sum(weight)/totwt),by=style]
},by=color]
# color style frac
# 1: red round 0.3466667
# 2: red pointy 0.3466667
# 3: red flat 0.3066667
# 4: green pointy 0.3333333
# 5: green flat 0.3200000
# 6: green round 0.3466667
# 7: blue flat 0.3866667
# 8: blue round 0.2933333
# 9: blue pointy 0.3200000
# 10: black round 0.3733333
# 11: black pointy 0.3333333
# 12: black flat 0.2933333
工作原理:在进入更精细的组(color
和 style
) 制表。
备选方案。如果 style
在每个 color
中重复并且这仅用于显示目的,请尝试 table
:
# A
widgets[,
prop.table(table(color,style),1)
]
# style
# color flat pointy round
# black 0.32 0.32 0.36
# blue 0.36 0.32 0.32
# green 0.32 0.36 0.32
# red 0.32 0.32 0.36
# B
widgets[,rep(1L,sum(weight)),by=.(color,style)][,
prop.table(table(color,style),1)
]
# style
# color flat pointy round
# black 0.2933333 0.3333333 0.3733333
# blue 0.3866667 0.3200000 0.2933333
# green 0.3200000 0.3333333 0.3466667
# red 0.3066667 0.3466667 0.3466667
对于 B,这会扩展数据,以便每个重量单位都有一个观测值。对于大数据,这样的扩展将不是一个好主意(因为它会花费太多内存)。此外,weight
必须是整数;否则,它的总和将被默默地截断为 1(例如,尝试 rep(1,2.5) # [1] 1 1
)。
使用 dplyr
df <- widgets %>%
group_by(color, style) %>%
summarise(count = n()) %>%
mutate(freq = count/sum(count))
df2 <- widgets %>%
group_by(color, style) %>%
summarise(count_w = sum(weight)) %>%
mutate(freq = count_w/sum(count_w))
为 color
中的每个 style
计算频率 table,然后为每一行查找 table 中该行的 style
的频率最后除以 color
中的行数。
widgets[, frac := table(style)[style] / .N, by = color]
给予:
> widgets
serial_no color style weight frac
1: 1 red round 1 0.36
2: 2 green pointy 2 0.36
3: 3 blue flat 3 0.36
4: 4 black round 4 0.36
5: 5 red pointy 5 0.32
6: 6 green flat 1 0.32
7: 7 blue round 2 0.32
8: 8 black pointy 3 0.32
9: 9 red flat 4 0.32
10: 10 green round 5 0.32
... etc ...
如果需要,这可以很容易地转换为 base 或 dplyr:
# base
prop <- function(x) table(x)[x] / length(x)
transform(widgets, frac = ave(style, color, FUN = prop))
# dplyr - uses prop function from above
library(dplyr)
widgets %>% group_by(color) %>% mutate(frac = prop(style)) %>% ungroup