#r #loops #sorting
Вопрос:
Я не новичок в R, но все еще очень новичок и учусь (поэтому объяснения очень приветствуются). У меня есть набор данных (165000 записей) родословной, который полностью зашифрован.
Моя цель: обеспечить, чтобы ни у кого не было даты рождения раньше, чем у их родителей. Если это так, то я хочу изменить эту дату рождения на NA (позже я сам превращу ее в пробел). Ниже приведен пример, аналогичный моему набору данных. (есть также люди с неизвестной датой рождения)
m <- data.frame(id = c(1 , 4, 7,11,15, 2, 3, 5,20,17, 6, 8,19,14,13, 9,12,10,16,18),
dad = c(NA,NA,NA, 4, 4,NA,NA,NA,18,7 ,NA,NA,14,7 ,5 ,NA, 5, 3, 9, 7),
mom = c(NA,NA,NA,2 ,8 ,NA,NA,NA,16,10,NA,NA,13, 6, 2,NA, 1, 1, 6,11),
yr = c(1977,1976,1977,1981,1984,1975,1976,NA,1989,1985,1978,1978,1988,NA,
1982,1978,1982,1980,1984,1985))
m1 <- transform(m, bornbefore = yr <= yr[match(mom, id)] | yr <= yr[match(dad, id)])
m2 <- transform(m1, yr_new = ifelse(bornbefore == TRUE, NA, yr)
Запуск этого кода только один раз все равно оставляет меня с некоторыми bornbefore == TRUE. Поэтому мне было интересно, есть ли способ использовать какие-либо функции цикла для этого (применить семейство, цикл и т. Д.)? Я очень теряюсь в туалете[ функции, так что помощь приветствуется.
Кроме того, мне было интересно, может ли это помочь отсортировать данные так, чтобы родители находились в наборе данных раньше потомков? простое использование m[order(m$yr),]
не работает, потому что иногда у потомства неправильная дата рождения, и тогда его ставят перед родителями.
Заранее спасибо за любую помощь, и я надеюсь, что мой вопрос ясен.
Комментарии:
1. С положительной стороны, у вас есть тест, сделанный до этого, на качество ваших данных, которые могут быть полезны при определении дат рождения потомства, если отношения {мать/отец} -> ребенок могут считаться надежными, поэтому, возможно, вы хотите вменить, а не исключить эти ошибочные записи. Я думаю, я говорю, что используйте bornbefore для индексирования плохих данных и создайте разумное правило, чтобы изменить их в соответствии с родословными и пометить их как вменяемые.
2. Концептуально я задаюсь вопросом, разумно ли то, что вы делаете. Основная теория, по-видимому, заключается в том, что если вы родились раньше своих родителей, ваша дата рождения неверна. Но что, если они родились раньше своих родителей? Тогда их дата рождения тоже должна быть НА. Итак, в каком порядке вы хотите применить эту логику?
3. @dash2 Я понимаю, о чем ты говоришь. Случай, когда родители иногда рождаются раньше своих родителей, также встречается в моем наборе данных. Но я использую R, чтобы «очистить»свой набор данных, а затем прогоню его через программу, которая вычислит для меня много вещей (что заняло бы у меня целую вечность в R). Одна из вещей, которую он делает, — это оценка даты рождения для лиц с неизвестными датами рождения на основе даты рождения их родителей и их потомков. с точки зрения порядка, я думаю, что было бы начать с особей в поколении 1 (старшее поколение), а затем перейти к родословной
4. это имеет смысл, и если вы знаете поколения, это естественный способ ограничить размер выполняемых вами соединений с базой данных
Ответ №1:
Объединения-это естественный путь:
library(dplyr)
m_dad <- left_join(m, m, by = c("dad" = "id"))
m_dad <- mutate(m_dad, yr.x = ifelse(yr.x >= yr.y, yr.x, NA))
m[] <- m_dad[1:4] # a nice trick to keep column names from m
m_mom <- left_join(m, m, by = c("mom" = "id"))
m_mom <- mutate(m_mom, yr.x = ifelse(yr.x >= yr.y, yr.x, NA))
m[] <- m_mom[1:4]
Комментарии:
1. Примечание: объединение больших данных может быть медленным. Если вы каким-то образом сможете разделить свою базу данных на отдельные линейки, это может помочь. Или это может быть достаточно быстро в любом случае. Или вы можете попробовать data.table для ускорения.
Ответ №2:
Возможно, это не самое элегантное решение, но оно должно сработать. Он использует комбинацию базовых R и dplyr:
m <- data.frame(id = c(1 , 4, 7,11,15, 2, 3, 5,20,17, 6, 8,19,14,13, 9,12,10,16,18),
dad = c(NA,NA,NA, 4, 4,NA,NA,NA,18,7 ,NA,NA,14,7 ,5 ,NA, 5, 3, 9, 7),
mom = c(NA,NA,NA,2 ,8 ,NA,NA,NA,16,10,NA,NA,13, 6, 2,NA, 1, 1, 6,11),
yr = c(1977,1976,1977,1981,1984,1975,1976,NA,1989,1985,1978,1978,1988,NA,
1982,1978,1982,1980,1984,1985))
library(dplyr)
m <- m %>% rename(dad_id = dad,
mom_id = mom)
dad <- m[,c("id", "yr")]
dad <- dad %>% rename(dad_id = id,
dad_yr = yr)
mom <- m[,c("id", "yr")]
mom <- mom %>% rename(mom_id = id,
mom_yr = yr)
m_new <- m %>%
left_join(dad, by = "dad_id") %>%
left_join(mom, by = "mom_id")
m_new$bornbefore <- ifelse((m_new$yr <= m_new$dad_yr | m_new$yr <= m_new$mom_yr), TRUE, FALSE)
m_new$yr <- ifelse(m_new$bornbefore == TRUE, NA, m_new$yr)