繁体   English   中英

如何使用 R 将用户 ID 随机分配给不同的日期

[英]How to randomly assign a user id to a different date using R

我有这样的数据集

mydata=structure(list(SAP = c("S985", "S985", "S985", "S985", "S985", 
"S985", "S985", "S985"), code = c(50000690L, 50000690L, 50000690L, 
50000690L, 801L, 50000690L, 50000690L, 50000690L), dt_start = c("18.01.2022 8:00", 
"18.01.2022 12:00", "18.01.2022 12:00", "18.01.2022 10:00", "22.01.2022 10:00", 
"22.01.2022 10:00", "22.01.2022 12:00", "22.01.2022 12:00"), 
    dt_end = c("18.01.2022 10:00", "18.01.2022 22:00", "18.01.2022 22:00", 
    "18.01.2022 20:00", "22.01.2022 20:00", "22.01.2022 20:00", 
    "22.01.2022 22:00", "22.01.2022 22:00"), person_number = c(938541L, 
    938541L, 938541L, 938541L, 754105L, 867801L, 865394L, 938541L
    )), class = "data.frame", row.names = c(NA, -8L))

在这个数据集中,我们看到列person_number=938541dt startdt end列中只有一个日期18.01 这意味着在这个日期他一个人工作(不要注意日期中的重复,这现在不重要)。 但总的来说,我们看到 whe 有 4 个唯一的 person_number(人)。

754105
867801
865394
938541

如果碰巧有人在某个日期工作,那么我们正在寻找一个唯一的personal_number,我们会在只有一个personal_number 的工作日期随机签署任何人。 例如像这样的期望结果

SAP code           dt_start                    dt_end         person_number
S985    50000690    18.01.2022 8:00     18.01.2022 10:00    938541
S985    50000690    18.01.2022 12:00    18.01.2022 22:00    938541
S985    50000690    18.01.2022 12:00    18.01.2022 22:00    938541
S985    50000690    18.01.2022 10:00    18.01.2022 20:00    938541
**S985  50000690    18.01.2022 12:00    18.01.2022 22:00    865394**
S985    801         22.01.2022 10:00    22.01.2022 20:00    754105
S985    50000690    22.01.2022 10:00    22.01.2022 20:00    867801
S985    50000690    22.01.2022 12:00    22.01.2022 22:00    865394
S985    50000690    22.01.2022 12:00    22.01.2022 22:00    938541

我随机选择了865394并将其粘贴在 18.01 日期。所以在 18.01 日期两个人工作而不是一个人。 您的帮助将不胜感激。 谢谢你。

两个选项都选择第一个dt_start / dt_end ,随机分配的person_number被分配到其中以增加单个工人。

旁注:您的时间戳应该是“真实的” POSIXt -class,原因有两个:(1)排序顺序现在是错误的,因为您有日-月-年; (2)如果你想计算差异等,你需要像数字一样。 我的两个解决方案都没有这样做,每个快速as.POSIXct(., format="%d.%m.%Y %H:%M")都可以。 如果列是characterPOSIXt ,这两种解决方案都可以按原样工作。

dplyr

library(dplyr)
persons <- unique(mydata$person_number)
mydata %>%
  group_by(date = substring(dt_start, 1, 10)) %>%
  summarize(
    n = n_distinct(person_number),
    across(-person_number, ~ .[1]),
    person_number = sample(setdiff(persons, person_number))[1]
  ) %>%
  filter(n == 1L) %>%
  select(-n, -date) %>%
  bind_rows(mydata)
# # A tibble: 9 x 5
#   SAP       code dt_start         dt_end           person_number
#   <chr>    <int> <chr>            <chr>                    <int>
# 1 S985  50000690 18.01.2022 8:00  18.01.2022 10:00        754105
# 2 S985  50000690 18.01.2022 8:00  18.01.2022 10:00        938541
# 3 S985  50000690 18.01.2022 12:00 18.01.2022 22:00        938541
# 4 S985  50000690 18.01.2022 12:00 18.01.2022 22:00        938541
# 5 S985  50000690 18.01.2022 10:00 18.01.2022 20:00        938541
# 6 S985       801 22.01.2022 10:00 22.01.2022 20:00        754105
# 7 S985  50000690 22.01.2022 10:00 22.01.2022 20:00        867801
# 8 S985  50000690 22.01.2022 12:00 22.01.2022 22:00        865394
# 9 S985  50000690 22.01.2022 12:00 22.01.2022 22:00        938541

data.table

library(data.table)
myDT <- as.data.table(mydata) # just for local testing, should use setDT(mydata)
persons <- unique(mydata$person_number)
rbindlist(list(
  myDT,
  myDT[, date := substring(dt_start, 1, 10)
    ][, cbind(.SD[1,], n = uniqueN(person_number), person_number = sample(setdiff(persons, person_number))[1]),
        by = date, .SDcols = -"person_number"
    ][ n == 1L,][, n := NULL]
  ), use.names = TRUE)
#       SAP     code         dt_start           dt_end person_number       date
#    <char>    <int>           <char>           <char>         <int>     <char>
# 1:   S985 50000690  18.01.2022 8:00 18.01.2022 10:00        938541 18.01.2022
# 2:   S985 50000690 18.01.2022 12:00 18.01.2022 22:00        938541 18.01.2022
# 3:   S985 50000690 18.01.2022 12:00 18.01.2022 22:00        938541 18.01.2022
# 4:   S985 50000690 18.01.2022 10:00 18.01.2022 20:00        938541 18.01.2022
# 5:   S985      801 22.01.2022 10:00 22.01.2022 20:00        754105 22.01.2022
# 6:   S985 50000690 22.01.2022 10:00 22.01.2022 20:00        867801 22.01.2022
# 7:   S985 50000690 22.01.2022 12:00 22.01.2022 22:00        865394 22.01.2022
# 8:   S985 50000690 22.01.2022 12:00 22.01.2022 22:00        938541 22.01.2022
# 9:   S985 50000690  18.01.2022 8:00 18.01.2022 10:00        754105 18.01.2022

这也可以受益于使用%>%进行管道以更好地显示数据流(即可读性),我选择反对它以不模糊包/方言。

这个替代方案(更简洁)源自 Henrik 的绝妙建议:

myDT[, date := substring(dt_start, 1, 10)
  ][ , if (uniqueN(person_number) == 1) {
         .SD[c(1, 1:.N)][1, person_number := sample(setdiff(persons, person_number), 1)]
       } else .SD, by = date]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM