[英]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=938541
在dt start
和dt 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")
都可以。 如果列是character
或POSIXt
,这两种解决方案都可以按原样工作。
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
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.