R:从列表中随机选择项目
R: Randomly Selecting Items from a List
我正在使用 R 编程语言。我想创建一个问题:
有4个人 : "person 1", "person 2", "person 3" ,"person 4"
有食品清单:"pizza", "apples", "tacos", "ice cream", "grapes", "olives", "sushi", "chocolate", "cake", "nachos", "pasta", "cookies", "popcorn", "soup"
一年中有几天:1 to 365
在这个问题中,人员列表是随机排序的。此列表的顺序决定谁先“选择”。
根据名单的顺序,名单开头的人将被分配4个随机号码:
Rand_1_1 (Person 1, First Random Number) : 第一个随机数将决定第一个人的“食物”数量允许选择(例如 3)
Rand_1_2 (Person 1, Second Random Number) : 第二个随机数将决定第一个人选择哪些“食物”与“Rand_1_1”对应的“食品”数量(例如“炸玉米饼”、“玉米片”、“汤”)
Rand_1_3(人1,第三个随机数):第三个随机数将决定该天的天数第一人称
Rand_1_4(第一个人,第四个随机数):第四个随机数决定第一个人的天数(例如,第 1 个人可能被指定为“41 到 160”天)。
这是为所有人完成的随机数分配过程:Rand_1_1、Rand_1_2、Rand_1_3、Rand_1_4、Rand_2_1, Rand_2_2, Rand_2_3, Rand_2_4, Rand_3_1, Rand_3_2, Rand_3_3, Rand_3_4, Rand_4_1 , Rand_4_2, Rand_4_3, Rand_4_4
但是,有一个逻辑约束:
“人”不能选择之前的“人”已经选择的“食品”(例如,如果第 1 人 selected 在第 2 人之前选择,如果第 1 个人选择了“披萨”,那么第 2 个人就不能选择“披萨”)
一个“人”不能选择之前“人”已经选择的“天数范围”
4个人都选完后,有可能可以保留一些“食物”和一些“日期范围” unselected。另一方面,假设如果第一个人选择第一个并且他碰巧 select 所有的“食物”——那么当然,其他人将没有“食物”。同样的逻辑适用于“日期范围”。
现在,我正在尝试在 R 中编写代码:
首先,我加载了库:
#load libraries
library(dplyr)
library(gtools)
其次,我创建的数据:
#create data
#variable 1: days of the year
days <- 1:365
#variable 2 : food
food <- c("pizza", "apples", "tacos", "ice cream", "grapes", "olives", "sushi", "chocolate", "cake", "nachos", "pasta", "cookies", "popcorn", "soup")
food_data <- data.frame(food)
food_data$id <- 1:nrow(food_data)
# people
people <- c("person 1", "person 2", "person 3" ,"person 4")
第三,我创建了人们选择的顺序:
# randomize order of people : this decides the order of who picks "days" and "food"
set.seed(123)
order_of_people = permute(people)
# in this example, "person 3" will pick first, "person 4" will pick second, "person 1" will pick third and "person 2" will pick last
order_of_people
[1] "person 3" "person 4" "person 1" "person 2"
我的问题: 我知道如何为每个人分配一个随机数,但我不知道如何分配随机数以符合逻辑约束。例如:
#choices for person 3 (according to the random seed, person 3 will pick 5 food items)
set.seed(120)
dim = dim(food_data)
#number of items selected by person 3
Rand_3_1 <- sample.int(dim[1], 1)
#which food items selected by person 3 (corresponding to the food_id : "3, 9, 6, 7, 4")
set.seed(120)
Rand_3_2 = c( sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1))
#which days selected by person 3 (according to this random seed, "65 to 87")
set.seed(120)
Rand_3_3 <- sample.int(365, 1)
Rand_3_4 <- sample.int(365, 1)
因此,我可以为每个人创建“selection frames”:
#Person 1
Rand_1_1 <- sample.int(dim[1], 1)
Rand_1_2 = c( #fill randomly with amount of items specified by Rand_1_1)
Rand_1_3 <- sample.int(365, 1)
Rand_1_4 <- sample.int(365, 1)
#Person 2
Rand_2_1 <- sample.int(dim[1], 1)
Rand_2_2 = c( #fill randomly with amount of items specified by Rand_2_1)
Rand_2_3 <- sample.int(365, 1)
Rand_2_4 <- sample.int(365, 1)
#Person 3
Rand_3_1 <- sample.int(dim[1], 1)
Rand_3_2 = c( #fill randomly with amount of items specified by Rand_3_1)
Rand_3_3 <- sample.int(365, 1)
Rand_3_4 <- sample.int(365, 1)
#Person 4
Rand_4_1 <- sample.int(dim[1], 1)
Rand_4_2 = c( #fill randomly with amount of items specified by Rand_4_1)
Rand_4_3 <- sample.int(365, 1)
Rand_4_4 <- sample.int(365, 1)
但我不知道如何做到这一点才能遵守逻辑约束。最后,我试图制作这样的东西:
#desired results
Person 1 : "apples, tacos" and "4-51"
Person 2: "cookies, nachos, cake, olives", and "56-180"
Person 3: "ice cream", and "200-214"
Person 4: "sushi, popcorn" and "350-365"
有人可以告诉我怎么做吗?
谢谢
这看起来很简单,除非我遗漏了什么,你有一份食物和日子的清单,所以每次你 运行 通过一个人并且只有 select 来自这些选项:
## initialize the inputs
set.seed(1)
foods <- letters[1:20]
nfoods <- sample(5, 4)
tmp <- list(unpicked = list(food = foods, days = 1:365))
## run it
tmp <- lapply(nfoods, function(x) tmp <<- f(tmp$unpicked$food, x, tmp$unpicked$days))
## summarize it
res <- sapply(seq_along(tmp), function(ii) {
x <- tmp[[ii]]
x <- sprintf('person %s: "%s" and "%s"', ii, toString(x$picked$food),
paste0(x$picked$days, collapse = '-'))
cat(x, sep = '\n')
invisible(x)
})
# person 1: "b" and "270-299"
# person 2: "s, a, k, g" and "306-336"
# person 3: "m, t, h" and "42-89"
# person 4: "j, f, q, o, l" and "129-210"
f <- function(food, n, days) {
# f(1:4, 3, 1:10)
food1 <- sample(food, n)
days1 <- split(days, cumsum(is.na(days)))
days1 <- sample(Filter(function(x) length(x) > 2, days1), 1)[[1]]
days1 <- sort(sample(sort(days1), 2))
days[do.call('seq', as.list(days1))] <- NA
list(
picked = list(food = food1, days = days1),
unpicked = list(food = setdiff(food, food1), days = days)
)
}
我正在使用 R 编程语言。我想创建一个问题:
有4个人 :
"person 1", "person 2", "person 3" ,"person 4"
有食品清单:
"pizza", "apples", "tacos", "ice cream", "grapes", "olives", "sushi", "chocolate", "cake", "nachos", "pasta", "cookies", "popcorn", "soup"
一年中有几天:
1 to 365
在这个问题中,人员列表是随机排序的。此列表的顺序决定谁先“选择”。
根据名单的顺序,名单开头的人将被分配4个随机号码:
Rand_1_1 (Person 1, First Random Number) : 第一个随机数将决定第一个人的“食物”数量允许选择(例如 3)
Rand_1_2 (Person 1, Second Random Number) : 第二个随机数将决定第一个人选择哪些“食物”与“Rand_1_1”对应的“食品”数量(例如“炸玉米饼”、“玉米片”、“汤”)
Rand_1_3(人1,第三个随机数):第三个随机数将决定该天的天数第一人称
Rand_1_4(第一个人,第四个随机数):第四个随机数决定第一个人的天数(例如,第 1 个人可能被指定为“41 到 160”天)。
这是为所有人完成的随机数分配过程:Rand_1_1、Rand_1_2、Rand_1_3、Rand_1_4、Rand_2_1, Rand_2_2, Rand_2_3, Rand_2_4, Rand_3_1, Rand_3_2, Rand_3_3, Rand_3_4, Rand_4_1 , Rand_4_2, Rand_4_3, Rand_4_4
但是,有一个逻辑约束:
“人”不能选择之前的“人”已经选择的“食品”(例如,如果第 1 人 selected 在第 2 人之前选择,如果第 1 个人选择了“披萨”,那么第 2 个人就不能选择“披萨”)
一个“人”不能选择之前“人”已经选择的“天数范围”
4个人都选完后,有可能可以保留一些“食物”和一些“日期范围” unselected。另一方面,假设如果第一个人选择第一个并且他碰巧 select 所有的“食物”——那么当然,其他人将没有“食物”。同样的逻辑适用于“日期范围”。
现在,我正在尝试在 R 中编写代码:
首先,我加载了库:
#load libraries
library(dplyr)
library(gtools)
其次,我创建的数据:
#create data
#variable 1: days of the year
days <- 1:365
#variable 2 : food
food <- c("pizza", "apples", "tacos", "ice cream", "grapes", "olives", "sushi", "chocolate", "cake", "nachos", "pasta", "cookies", "popcorn", "soup")
food_data <- data.frame(food)
food_data$id <- 1:nrow(food_data)
# people
people <- c("person 1", "person 2", "person 3" ,"person 4")
第三,我创建了人们选择的顺序:
# randomize order of people : this decides the order of who picks "days" and "food"
set.seed(123)
order_of_people = permute(people)
# in this example, "person 3" will pick first, "person 4" will pick second, "person 1" will pick third and "person 2" will pick last
order_of_people
[1] "person 3" "person 4" "person 1" "person 2"
我的问题: 我知道如何为每个人分配一个随机数,但我不知道如何分配随机数以符合逻辑约束。例如:
#choices for person 3 (according to the random seed, person 3 will pick 5 food items)
set.seed(120)
dim = dim(food_data)
#number of items selected by person 3
Rand_3_1 <- sample.int(dim[1], 1)
#which food items selected by person 3 (corresponding to the food_id : "3, 9, 6, 7, 4")
set.seed(120)
Rand_3_2 = c( sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1), sample.int(dim[1], 1))
#which days selected by person 3 (according to this random seed, "65 to 87")
set.seed(120)
Rand_3_3 <- sample.int(365, 1)
Rand_3_4 <- sample.int(365, 1)
因此,我可以为每个人创建“selection frames”:
#Person 1
Rand_1_1 <- sample.int(dim[1], 1)
Rand_1_2 = c( #fill randomly with amount of items specified by Rand_1_1)
Rand_1_3 <- sample.int(365, 1)
Rand_1_4 <- sample.int(365, 1)
#Person 2
Rand_2_1 <- sample.int(dim[1], 1)
Rand_2_2 = c( #fill randomly with amount of items specified by Rand_2_1)
Rand_2_3 <- sample.int(365, 1)
Rand_2_4 <- sample.int(365, 1)
#Person 3
Rand_3_1 <- sample.int(dim[1], 1)
Rand_3_2 = c( #fill randomly with amount of items specified by Rand_3_1)
Rand_3_3 <- sample.int(365, 1)
Rand_3_4 <- sample.int(365, 1)
#Person 4
Rand_4_1 <- sample.int(dim[1], 1)
Rand_4_2 = c( #fill randomly with amount of items specified by Rand_4_1)
Rand_4_3 <- sample.int(365, 1)
Rand_4_4 <- sample.int(365, 1)
但我不知道如何做到这一点才能遵守逻辑约束。最后,我试图制作这样的东西:
#desired results
Person 1 : "apples, tacos" and "4-51"
Person 2: "cookies, nachos, cake, olives", and "56-180"
Person 3: "ice cream", and "200-214"
Person 4: "sushi, popcorn" and "350-365"
有人可以告诉我怎么做吗?
谢谢
这看起来很简单,除非我遗漏了什么,你有一份食物和日子的清单,所以每次你 运行 通过一个人并且只有 select 来自这些选项:
## initialize the inputs
set.seed(1)
foods <- letters[1:20]
nfoods <- sample(5, 4)
tmp <- list(unpicked = list(food = foods, days = 1:365))
## run it
tmp <- lapply(nfoods, function(x) tmp <<- f(tmp$unpicked$food, x, tmp$unpicked$days))
## summarize it
res <- sapply(seq_along(tmp), function(ii) {
x <- tmp[[ii]]
x <- sprintf('person %s: "%s" and "%s"', ii, toString(x$picked$food),
paste0(x$picked$days, collapse = '-'))
cat(x, sep = '\n')
invisible(x)
})
# person 1: "b" and "270-299"
# person 2: "s, a, k, g" and "306-336"
# person 3: "m, t, h" and "42-89"
# person 4: "j, f, q, o, l" and "129-210"
f <- function(food, n, days) {
# f(1:4, 3, 1:10)
food1 <- sample(food, n)
days1 <- split(days, cumsum(is.na(days)))
days1 <- sample(Filter(function(x) length(x) > 2, days1), 1)[[1]]
days1 <- sort(sample(sort(days1), 2))
days[do.call('seq', as.list(days1))] <- NA
list(
picked = list(food = food1, days = days1),
unpicked = list(food = setdiff(food, food1), days = days)
)
}