r - 如何根据所在组的大小为项目添加权重
问题描述
我有一个看起来像这样的数据集
product material
product1 wheat
product1 water
product1 tomato
product2 milk
product3 basil
product3 garlic
我有一条规则,如果产品由一种材料组成,那么该材料就是产品的 100%。如果它由两种材料组成,第一种材料占总数的 60%,第二种材料占总数的 40%。如果一个产品由 3 种材料组成,第一种材料占 70%,第二种材料占 20%,最后一种材料占 10%。我想添加一列这些权重,但我不知道如何解决这个问题。规则最多5种材料,重量需要容易改变。最后我希望上面的数据看起来像这样
product material weight
product1 wheat 0.7
product1 water 0.2
product1 tomato 0.1
product2 milk 1
product3 basil 0.6
product3 pizza 0.4
我就是这样开始的
df = tribble(
~product, ~material_type,
"product1", "wheat",
"product1", "Water",
"product1", "tomato",
"product2", "milk",
"product3", "basil",
"product3", "garlic")
df %>%
group_by(product) %>%
mutate(n = n())
product material_type n
<chr> <chr> <int>
1 product1 wheat 3
2 product1 Water 3
3 product1 tomato 3
4 product2 milk 1
5 product3 basil 2
6 product3 garlic 2
这确实给了我每组中有多少材料,从这里我不知道如何进一步了解,希望这里有人有一个可以帮助我的好主意。
编辑:
我尝试添加 case_when 建议,但没有奏效:
df %>%
group_by(product) %>%
mutate(n = n()) %>%
mutate(weight = case_when(n == 5 ~ c(.4, .3, .1, .1, .1),
n== 4 ~ c(.5, .3, .1, .1),
n ==3 ~ c(.7, .2, .1),
n == 2 ~ c(0.6, 0.4),
TRUE ~ 1))
Error: `n == 5 ~ c(0.4, 0.3, 0.1, 0.1, 0.1)`, `n == 4 ~ c(0.5, 0.3, 0.1, 0.1)`, `n == 2 ~ c(0.6, 0.4)` must be length 3 or one, not 5, 4, 2
Call `rlang::last_error()` to see a backtrace.
解决方案
我们可以创建一个键/值,list
然后n()
根据name
list
library(dplyr)
library(tidyr)
lst1 <- list(`5` = c(.4, .3, .1, .1, .1), `4` = c(.5, .3, .1, .1),
`3` = c(.7, .2, .1), `2` =c(0.6, 0.4), `1` = 1 )
df %>%
group_by(product) %>%
summarise(weight = list(lst1[[as.character(n())]])) %>%
unnest(c(weight)) %>%
select(-product) %>%
bind_cols(df, .)
# A tibble: 6 x 3
# product material_type weight
#* <chr> <chr> <dbl>
#1 product1 wheat 0.7
#2 product1 Water 0.2
#3 product1 tomato 0.1
#4 product2 milk 1
#5 product3 basil 0.6
#6 product3 garlic 0.4
或者unnest
同时使用“material_type”和“weight”并避免bind_cols
df %>%
group_by(product) %>%
summarise(material_type = list(material_type),
weight = list(lst1[[as.character(n())]])) %>%
unnest(c(material_type, weight))
或者另一种选择是if/else
df %>%
group_by(product) %>%
mutate(weight = if(n() == 5) c(.4, .3, .1, .1, .1)
else if(n() == 4) c(.5, .3, .1, .1)
else if(n() == 3) c(.7, .2, .1)
else if(n() == 2) c(0.6, 0.4)
else 1)
推荐阅读
- php - 使用 while 循环对多维数组进行编码
- java - 如何在数据库分区表上定义 JPA 实体
- javascript - 无法使用赛普拉斯查询 MongoDB 的 ObjectId
- android-studio - 更改单元测试的 Android Studio 选项卡颜色
- c - 使用 fork() 创建 n 个子进程并在之后处理它们
- javascript - 如何将换行功能添加到?
- php - 如何解决这个错误(mail(): SMTP server response: 530 5.7.0 Must issue a STARTTLS command first. i2sm7399406pjt.19 - gsmtp)
- python - Pyrosm 加载节点和边 - 输入必须是有效的几何对象
- memory-leaks - Ryzen 7 2700X 上的 HAXM 启动错误 - 系统崩溃原因的线索?
- webgl - 如何为浮点纹理设置数据?