#r
#r
Вопрос:
Допустим, у меня есть df с 4 столбцами. Как я могу добавить столбец, который указывает, соответствует ли строка в столбце 1 строке в любом из столбцов 1-3?
df
species_A species_1 species_2 species_3
1 Clostridium breve Clostridium breve Eggerthella lenta Bacillus cereus
2 Splactus blandum Splactus plantarum Splactus pentosus Clostridium adolescentis
3 Rotoroides ovatus Rotoroides ovatus Pseudomonas oryzihabitans Stenotrophomonas maltophilia
4 Bacillus licheniformis Phytorotor sp. Cutirotorium acnes Rotoroides ovatus
5 Clostridium longum Clostridium longum Sphingomonas melonis Phytorotor sp.
6 Odorirotor splanchnicus Clostridium longum Odorirotor splanchnicus Stenotrophomonas maltophilia
Я хочу добавить столбец ‘match’ с T / F в зависимости от того, соответствует ли species_A species_1 ИЛИ species_2 ИЛИ species_3:
species_A species_1 species_2 species_3 Matches
1 Clostridium breve Clostridium breve Eggerthella lenta Bacillus cereus TRUE
2 Splactus bandum Splactus plantarum Splactus pentosus Clostridium adolescentis TRUE
3 Rotoroides ovatus Rotoroides ovatus Pseudomonas oryzihabitans Stenotrophomonas maltophilia TRUE
4 Bacillus licheniformis Phytorotor sp. Cutirotorium acnes Rotoroides ovatus FALSE
5 Clostridium longum Clostridium longum Sphingomonas melonis Phytorotor sp. TRUE
6 Odorirotor splanchnicus Clostridium longum Odorirotor splanchnicus Stenotrophomonas maltophilia TRUE
Основываясь на других потоках, я пытался использовать lapply и sapply, но, похоже, я не могу передать столбец species_A в виде набора шаблонов.
lapply(df[2:4], function(x) match(x, d$species_A))
sapply(df[2:4],
function(x) grepl(d$species_A, x, ignore.case = TRUE))
Ответ №1:
Попробуйте это:
rowSums(df$species_A == df[2:4]) > 0
Ваши данные трудно импортировать из-за пробелов (используйте dput(df)
для совместного использования копируемой / вставляемой версии фрейма данных), поэтому я продемонстрирую некоторые поддельные данные:
## copy/pasteable data:
df = data.frame(
species_A = c("A", "B", "C", "D"),
species_1 = c("A", "A", "X", "X"),
species_2 = c("A", "B", "X", "X"),
species_3 = c("A", "X", "X", "D")
)
df
# species_A species_1 species_2 species_3
# 1 A A A A
# 2 B A B X
# 3 C X X X
# 4 D X X D
## make comparisons
df$species_A == df[2:4]
# species_1 species_2 species_3
# [1,] TRUE TRUE TRUE
# [2,] FALSE TRUE FALSE
# [3,] FALSE FALSE FALSE
# [4,] FALSE FALSE TRUE
## see if there are any TRUEs
rowSums(df$species_A == df[2:4]) > 0
# [1] TRUE TRUE FALSE TRUE
## put it together
df$result = rowSums(df$species_A == df[2:4]) > 0
df
# species_A species_1 species_2 species_3 result
# 1 A A A A TRUE
# 2 B A B X TRUE
# 3 C X X X FALSE
# 4 D X X D TRUE
lapply
и sapply
это не лучший выбор здесь, потому что они перебирают столбцы 2: 4 и возвращают отдельные результаты для столбцов 2: 4. Мы также могли бы использовать их с rowSums
, sapply(df[2:4], "==", df$species_A)
это более длинный способ записи df$species_A == df[2:4]
.
Комментарии:
1. Оказывается, это не работает в моей установке (R версии 3.6.2). Я получаю следующее, когда запускаю «df $ species_A == df [2: 4]»: Ошибка в df $ species_A == df [2: 4]: сравнение этих типов дополнительно не реализовано: Предупреждающие сообщения: 1: Несовместимые методы («Ops.factor», «Ops.data.frame») для «==» 2: В df $ species_A == df[2:4] : более длинная длина объекта не кратна более короткой длине объекта
2. Ах, похоже, что по крайней мере некоторые из ваших столбцов являются факторами. Преобразуйте их в
character
векторы. Что-то вродеdf[] = lapply(df, as.character)
. (R 4.0 переключил значение по умолчанию для фреймов данных сfactor
наcharacter
— изменение, которое ожидалось долгое время.)