R случайным образом присваивает 1 или 0 в зависимости от условий

Для такого набора данных

    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")]), но это не сработало. Любое предложение очень ценится. Заранее спасибо.

Сгруппируйте по MainID и DOB и выполните условную логику по группам. (Логика группировки не совсем ясна из вашего описания и примера, но это может означать просто случайное присвоение 0 или 1 каждой строке в любой такой группе с N>1 и 0, если N==1)

Tobo 20.02.2024 00:24

@Тобо, извини, я обновил свой вопрос, это полезно?

Sundown Brownbear 20.02.2024 00:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Непонятно, хотите ли вы 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:1

дплир

library(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

база R

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 — если только у меня не галлюцинации после того, как я зашел из паба! Судя по галочке, ваша догадка верна, хотя пример согласуется и с другими закономерностями.

Tobo 20.02.2024 01:35

о да, верно... так что моя предосторожность оправдана... Пожалуй, я на минутку отложу пиво...

r2evans 20.02.2024 02:03

@r2evans, я получаю разные результаты на разных итерациях. Если я запущу скрипт 10 раз, я получу правильные результаты в 2 случаях из 10.

Sundown Brownbear 20.02.2024 05:52

Пожалуйста, определите «правильные результаты». Например, вы имеете в виду, что вам требуется хотя бы один 0 и один 1 для каждой MainID, DOB группы? Если да, то посмотрите мое редактирование: оно более осторожно относится к использованию некоторых атрибутов за пределами чисто случайной выборки.

r2evans 20.02.2024 06:12

@r2evans, я получаю сообщение об ошибке: невозможно взять выборку, превышающую генеральную совокупность, когда replace=false

Sundown Brownbear 21.02.2024 08:20

Да, это определение выборки. Если у вас есть 5 вещей для пробы и вы берете одну случайным образом без замены, останется 4, и вы не сможете взять ту же самую еще раз. Можно взять еще, потом осталось 3. После того, как вы взяли 5 вещей без замены, пробовать уже нечего. Если вы производите пробу с заменой, начиная с 5, вы берете одну и записываете то, что взяли, затем кладете ее обратно, теперь у вас есть 5 вещей, доступных для повторной выборки. С заменой вы можете делать это целый день.

r2evans 21.02.2024 12:43

Попробуйте еще раз @SundownBrownbear, образцы данных не вызвали проблему, думаю, я устранил проблему (не воспроизводя ее локально).

r2evans 21.02.2024 13:56

@r2evans, Спасибо. что такое nr>4? Это выдает ошибку.

Sundown Brownbear 21.02.2024 21:15

Это ошибка на стороне dplyr, исправлена, так и должно быть n() > 4

r2evans 21.02.2024 21:24

См. мою правку, чтобы узнать о, казалось бы, сложном sample(c(0:1, sample(..)))

r2evans 21.02.2024 21:29

Другие вопросы по теме

Похожие вопросы

Постройте все графики, созданные в функции, с минимальным диапазоном оси Y, необходимым для отображения доверительного интервала (r)
Как получить названия и цены с веб-страницы с помощью rvest
R блестящий — возврат редактируемой таблицы данных из модуля
Как очистить данные из json в R с помощью Rvest?
Компиляция libR (из статистического пакета R) как отдельной библиотеки C для java+jni
Повышение скорости моделирования Санкт-Петербурга
Как настроить количество десятичных знаков в значениях по умолчанию, отображаемых во входной матрице и используемых в последующих вычислениях, без использования округления?
Ggplot — Цветная геометрическая рабочий пример с заполненными точками
Ошибка: «нет текущего устройства для записи» для базового теста графика R в devtools::test()
Отображение предельных эффектов с использованием avg_slopes() для переходов определенных уровней в моделях plm с условиями взаимодействия