У меня есть 2 фрейма данных, каждый из которых я хочу использовать в качестве условия для применения во втором фрейме данных. Вот их пример:
condition_df <- data.frame(
type = c("3701","3801","4901","4901", "3701"),
position = c(51,51, 22,22, 13),
subtype = c("M", "M","D","K", "E")
)
df <- data.frame(
id = 1:5,
type1 = c("3701", "4901", "4902", "4903", "1501"),
type2 = c("3801", "4901", "4901","5050","6069"),
type3 = c("3901", "5001", "8901","5050","6069"),
type4 = c("4001", "3901", "7901","5050","6069"),
`51` = c("M", "A", "M", "M", "A"),
`22` = c("D", "D", "K", "A", "D"),
`13` = c("E", "G", "E", "E", "G"),
`55` = c("M", "A", "M", "M", "A"),
`25` = c("D", "D", "K", "A", "D"),
`16` = c("E", "G", "E", "E", "G"), check.names = FALSE
)
поэтому я хочу получить оценку во втором фрейме данных (df), и я хочу ее применить, используя строки фрейма данных условия для цикла по каждой строке фрейма данных. Условие состоит в том, что если тип отсутствует в столбцах df (type1:type4), то найдите столбец с именем == позиции (в условии_df) и подсчитайте количество букв в этом столбце, которые совпадают только с подтип в условии_df. Итоговая оценка должна представлять собой сумму всех условий Condition_df для каждого идентификатора в df. Пример. Оценка идентификатора 1 равна только 1, поскольку мы получили 0 для первого и последнего условий (поскольку у него есть тип, поэтому мы игнорируем подтип) и получили 1, поскольку он имеет второй подтип «D» и не имеет его типа. Любая помощь приветствуется.
Я попробовал что-то вроде этого, но не сработало:
for(i in seq_len(nrow(condition_df))) {
for(j in seq_len(nrow(df))) {
type <- condition_df$type[i]
position <- as.character(condition_df$position[i])
subtype <- condition_df$subtype[i]
df<-df %>%
mutate(cir_score=case_when(!any(across(starts_with("type"))==type)~sum(get(as.character(position))==subtype),
TRUE~0
))
}
}
@user2974951 user2974951 Спасибо за ваши комментарии, ожидаемый результат аналогичен ответу Эдварда ниже.
Поверните в длинную форму столбцы позиций (51, 22, ...), а затем присоединитесь к фрейму данных условия. Затем отфильтруйте строки, в которых тип соответствует типам 1–4, тогда оценка будет равна количеству записей, оставшихся для каждого идентификатора.
full_join(df,
pivot_longer(df, -c(id, starts_with("type")),
names_to = "position", values_to = "subtype",
names_transform=list(position=as.integer)) |>
inner_join(condition_df, by=c("position", "subtype"), relationship = "many-to-many") |>
filter(!if_any(matches("type\\d+"), ~ .x==type)) |>
distinct(id, position, subtype) |>
count(id, name = "score"),
by = "id") |>
mutate(score=replace_na(score, 0))
id type1 type2 type3 type4 51 22 13 55 25 16 score
1 1 3701 3801 3901 4001 M D E M D E 1
2 2 4901 4901 5001 3901 A D G A D G 0
3 3 4902 4901 8901 7901 M K E M K E 2
4 4 4903 5050 5050 5050 M A E M A E 2
5 5 1501 6069 6069 6069 A D G A D G 1
Большое спасибо за публикацию этого ответа. Ожидаемый результат (оценка) правильный; однако я попробовал код на своих реальных данных, но, к сожалению, он не сработал. Проблема в том, чтоcondition_df может иметь несколько значений типа для одной и той же позиции, и это не обнаруживается с помощью внутреннего соединения. Есть ли способ изменить этот код? Было бы здорово, если бы решение включало случай, когда я мог бы добавить больше условий на случай отсутствия доступных значений. Очень ценю вашу помощь.
@Эрвард, я получил это предупреждение, когда проводил анализ моих реальных данных In full_join(., condition_df2) : Detected an unexpected many-to-many relationship between
x` и y
. ℹ Строка 120 из x
соответствует нескольким строкам из y
. ℹ Строка 13 y
соответствует нескольким строкам x
. ℹ Если ожидается связь «многие-ко-многим», установите relationship = "many-to-many"
, чтобы отключить это предупреждение.`
Вам нужно будет опубликовать более репрезентативный пример ваших данных.
Да, это правда, я пропустил это и попытаюсь привести новый пример. Спасибо
Я отредактировал фрейм данных условия, чтобы он был максимально приближен к моим реальным данным. Извините, я это пропустил.
Смотрите обновление. Возможно, сейчас это не лучший способ.
Не могли бы вы опубликовать желаемый результат?