Для такого набора данных
MainID SubID DOB BMI
1234 1234_A Feb-19-2024 10.1
1235 1235_A Jan-11-2023 17.23
1235 1235_B Jan-11-2023 19.11
5136 5136_A May-17-2021 21.87
5136 5136_B May-17-2021 14.18
5136 5136_C May-17-2021 18.11
3357 3357-A Oct-06-2023 24.10
9124 9124-B July-01-2021 12.09
9124 9124-B July-01-2021 15.06
Я пытаюсь случайным образом присвоить значение 0 или 1, только если значения MainID и DOB одинаковы, SubID отличается. Ожидание такого набора данных
MainID SubID DOB BMI Col1
1234 1234_A Feb-19-2024 10.1 0
1235 1235_A Jan-11-2023 17.23 0
1235 1235_B Jan-11-2023 19.11 1
3357 3357-A Oct-06-2023 24.10 0
5136 5136_A May-17-2021 21.87 0
5136 5136_B May-17-2021 14.18 0
5136 5136_C May-17-2021 18.11 1
9124 9124-B July-01-2021 12.09 0
9124 9124-B July-01-2021 15.06 0
Здесь только строкам с идентификаторами 1235 и 5136 присваиваются значения 0 или 1, поскольку повторяющиеся строки имеют одинаковые MainID, DOB и разные SubID.
Я пробовал варианты с ifelse и duplicated(df[c("MainID", "DOB")]), но это не сработало. Любое предложение очень ценится. Заранее спасибо.
@Тобо, извини, я обновил свой вопрос, это полезно?





Непонятно, хотите ли вы 0:1пробу с заменой. Я предполагаю всегда 0:1 и замену с заменой только тогда, когда количество строк в группе больше 2.
В начале кода как dplyr, так и base-R есть фрагмент, похожий на этот.
sample(c(0:1, sample(0:1, size = n()-2, replace = (n() > 4))))
0 и один 1; если бы мы это сделали sample(0:1, size=n(), replace=TRUE), возможно (хотя и маловероятно), что у нас могут быть все 0 или все 1, и я делаю вывод, что нам нужно/нужно хотя бы по одному из каждого;c(0:1, ..), гарантируя наличие каждого числа;sample создавал размер n() - 2 (на 2 меньше, чем строк); если рядов всего четыре, то внешнего 0:1 и внутреннего 0:1 будет достаточно, поэтому технически замена нам не нужна, следовательно replace=(n() > 4)0:1 и может иметь ноль или более 0 и 1 в зависимости от количества строк в группе, нам нужно случайным образом изменить их порядок (потому что мы не хотим, чтобы первые два быть всегда 0:1library(dplyr)
set.seed(42)
quux |>
mutate(
Col1 = if (n_distinct(SubID) > 1) {
sample(c(0:1, sample(0:1, size = n()-2, replace = (n() > 4))))
} else 0,
.by = c(MainID, DOB)
)
# MainID SubID DOB BMI Col1
# 1 1234 1234_A Feb-19-2024 10.10 0
# 2 1235 1235_A Jan-11-2023 17.23 0
# 3 1235 1235_B Jan-11-2023 19.11 1
# 4 5136 5136_A May-17-2021 21.87 0
# 5 5136 5136_B May-17-2021 14.18 1
# 6 5136 5136_C May-17-2021 18.11 0
# 7 3357 3357-A Oct-06-2023 24.10 0
# 8 9124 9124-B July-01-2021 12.09 0
# 9 9124 9124-B July-01-2021 15.06 0
ave(seq_len(nrow(quux)), quux[, c("MainID", "DOB")],
FUN = function(ind) {
nr <- length(ind)
nsub <- length(unique(quux$SubID[ind]))
if (nsub > 1) sample(c(0:1, sample(0:1, size = nr-2, replace = (nr>4)))) else 0
})
# [1] 0 0 1 0 1 0 0 0 0
Данные
quux <- structure(list(MainID = c(1234L, 1235L, 1235L, 5136L, 5136L, 5136L, 3357L, 9124L, 9124L), SubID = c("1234_A", "1235_A", "1235_B", "5136_A", "5136_B", "5136_C", "3357-A", "9124-B", "9124-B"), DOB = c("Feb-19-2024", "Jan-11-2023", "Jan-11-2023", "May-17-2021", "May-17-2021", "May-17-2021", "Oct-06-2023", "July-01-2021", "July-01-2021"), BMI = c(10.1, 17.23, 19.11, 21.87, 14.18, 18.11, 24.1, 12.09, 15.06)), class = "data.frame", row.names = c(NA, -9L))
В примере указано более двух SubID — если только у меня не галлюцинации после того, как я зашел из паба! Судя по галочке, ваша догадка верна, хотя пример согласуется и с другими закономерностями.
о да, верно... так что моя предосторожность оправдана... Пожалуй, я на минутку отложу пиво...
@r2evans, я получаю разные результаты на разных итерациях. Если я запущу скрипт 10 раз, я получу правильные результаты в 2 случаях из 10.
Пожалуйста, определите «правильные результаты». Например, вы имеете в виду, что вам требуется хотя бы один 0 и один 1 для каждой MainID, DOB группы? Если да, то посмотрите мое редактирование: оно более осторожно относится к использованию некоторых атрибутов за пределами чисто случайной выборки.
@r2evans, я получаю сообщение об ошибке: невозможно взять выборку, превышающую генеральную совокупность, когда replace=false
Да, это определение выборки. Если у вас есть 5 вещей для пробы и вы берете одну случайным образом без замены, останется 4, и вы не сможете взять ту же самую еще раз. Можно взять еще, потом осталось 3. После того, как вы взяли 5 вещей без замены, пробовать уже нечего. Если вы производите пробу с заменой, начиная с 5, вы берете одну и записываете то, что взяли, затем кладете ее обратно, теперь у вас есть 5 вещей, доступных для повторной выборки. С заменой вы можете делать это целый день.
Попробуйте еще раз @SundownBrownbear, образцы данных не вызвали проблему, думаю, я устранил проблему (не воспроизводя ее локально).
@r2evans, Спасибо. что такое nr>4? Это выдает ошибку.
Это ошибка на стороне dplyr, исправлена, так и должно быть n() > 4
См. мою правку, чтобы узнать о, казалось бы, сложном sample(c(0:1, sample(..)))
Сгруппируйте по
MainIDиDOBи выполните условную логику по группам. (Логика группировки не совсем ясна из вашего описания и примера, но это может означать просто случайное присвоение 0 или 1 каждой строке в любой такой группе с N>1 и 0, если N==1)