【问题标题】:R: Randomly Selecting Items from a ListR:从列表中随机选择项目
【发布时间】:2021-11-17 08:14:00
【问题描述】:

我正在使用 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(第一个随机数,第一个随机数):第一个随机数将决定第一个人可以选择的“食物”数量(例如 3 个)

  • Rand_1_2 (Person 1, Second Random Number) : 第二个随机数将根据“Rand_1_1”对应的“食物”数量决定第一个人选择哪些“食物”(例如“炸玉米饼”、“玉米片”、“汤”)

  • Rand_1_3(第一个人,第三个随机数):第三个随机数将决定第一个人的天数

  • Rand_1_4(第 1 个人,第四个随机数):第四个随机数将决定第一个人的天数的另一个界限(例如,第 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、

但是,有一个逻辑约束

  • “人”不能选择之前“人”已经选择的“食物”(例如,如果人 1 在人 2 之前选择了选择,如果人 1 选择了“披萨”,那么人 2不能选择“披萨”)

  • “人”不能选择前面“人”已经选择的“天数范围”

  • 在所有 4 人都完成选择后,有可能某些“食品”和某些“日期范围”可以保持未选择状态。另一方面,假设如果第 1 个人首先选择并且他碰巧选择了所有“食物”——那么当然,其他人将没有“食物”。同样的逻辑也适用于“日期范围”。

现在,我正在尝试在 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)

因此,我可以为每个人创建“选择框架”:

#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"

有人可以告诉我怎么做吗?

谢谢

【问题讨论】:

    标签: r list random data-manipulation


    【解决方案1】:

    这似乎很简单,除非我错过了什么,你有一份食物和日子的清单,所以每次你遇到一个人时,只要跟踪可用的选项,然后只从这些选项中选择:

    ## 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)
      )
    }
    

    【讨论】:

    • @rawr:非常感谢您的回答!为什么以下代码行很重要? nfoods
    • @Noob 确定只需将其更改为您想要的任何内容,但总和应为
    • 我不确定我是否理解?在这个例子中 "sample(5, 4)" ,是否有最少的食物可供选择?有上限吗?
    • 最小值为1,最大值为5,你可以随意更改
    猜你喜欢
    • 1970-01-01
    • 2012-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多