我创建了一个名为数据的表。该表包含一个非唯一 ID 字段。
data <- data.frame(ID = sample(c(1:5), 10, replace = T))
我有另一个名为概率的表,其中包含 ID 字段的匹配项、相应的比率和名称:
probabilities <- data.frame(ID = c(1,1,2,2,3,3,4,4,4,5), ratio = c(0.9, 0.1, 0.4, 0.6, 0.8, 0.2, 0.3, 0.3, 0.4, 1.0), name = c("A", "B", "A", "C", "F", "G", "B", "C", "G", "F"))
我正在尝试在数据表中创建一个名为 name 的新变量。这将根据比率列使用概率表中的名称变量填充。
比如数据表中任何ID为1的应该有90%的几率是A,10%的几率是B。ID为4的应该有30%的几率变成B,30%的几率变成B C 和 40% 的机会是 G,等等。
有谁知道这是如何实现的?
我尝试了以下但出现错误:
#load packages
library(dplyr)
#create new variable called name
data <- data %>%
mutate(name = sample(probabilities$name[ID=probabilities$ID],
size = n(),
prop = probabilities$ratio[ID=probabilities$ID],
replace = TRUE))
mutate()
中的错误:
!计算 name = sample(...)
时出现问题。
sample()
错误导致:
!未使用的参数 (prop = probabilities$ratio[name = probabilities$name])
base R 解决方案,使用 sapply() 和 sample():
data$name <- sapply( data$ID, function(ID) sample(x = probabilities[probabilities$ID==ID,"name"],prob = probabilities[probabilities$ID==ID,"ratio"],size = 1))
一种方法是
count()
你的ID,加入概率数据,然后使用reframe()
按ID抽样:
library(dplyr)
set.seed(99)
data <- data.frame(ID = sample(c(1:5), 10, replace = T))
data %>%
count(ID) %>%
left_join(probabilities, by = "ID") %>%
reframe(name = sample(name, first(n), prob = ratio, replace = TRUE), .by = ID)
ID name
1 1 A
2 2 C
3 2 C
4 3 F
5 4 B
6 4 C
7 4 B
8 4 G
9 5 F
10 5 F
要保留所有vars,可以将数据匹配回原来的顺序,绑定结果:
set.seed(99)
data <- data.frame(ID = sample(c(1:5), 10, replace = T), other_var = 1:10)
data |>
count(ID) |>
left_join(probabilities, by = "ID") |>
reframe(name = sample(name, first(n), prob = ratio, replace = TRUE), .by = ID) %>%
slice(pmatch(data$ID, ID)) %>%
select(name) %>%
bind_cols(data, .)
ID other_var name
1 1 1 A
2 4 2 B
3 5 3 F
4 3 4 F
5 2 5 C
6 2 6 C
7 5 7 F
8 4 8 C
9 4 9 B
10 4 10 G
使用
data.table
非相等连接:
library(data.table)
set.seed(969943335)
data <- data.frame(ID = sample(c(1:5), 10, replace = T))
probabilities <- data.frame(ID = c(1,1,2,2,3,3,4,4,4,5), ratio = c(0.9, 0.1, 0.4, 0.6, 0.8, 0.2, 0.3, 0.3, 0.4, 1.0), name = c("A", "B", "A", "C", "F", "G", "B", "C", "G", "F"))
setDT(probabilities)[,cr := cumsum(ratio), ID][setDT(data)[,r := runif(.N)], .(ID, name), on = .(ID, cr > r), mult = "first"]
#> ID name
#> 1: 1 A
#> 2: 5 F
#> 3: 1 A
#> 4: 4 B
#> 5: 1 A
#> 6: 2 A
#> 7: 5 F
#> 8: 1 A
#> 9: 1 B
#> 10: 5 F