#r
#r
Вопрос:
Итак, у меня есть фрейм данных, подобный этому, с названиями видов, присутствующих в трех странах, с некоторыми NAS в странах, где определенный вид не существует:
Country_A | Country_B | Country_C
-----------------------------------------------------
Tilapia guineensis | NA | Tilapia guineensisi
Tilapia zillii | Tilapia zillii | Tilapia zillii
NA | Fundulus rubrifrons | Fundulus rubrifrons
Eutrigla gurnardus | Eutrigla gurnardus | NA
Sprattus sprattus | NA | NA
То, что я пытаюсь сделать, это в основном проверить, присутствует ли вид в одной, двух или трех странах, и создать фрейм данных, который будет выглядеть примерно так:
Species name | Country_A | Country_B | Country_C
---------------------------------------------------------------------
Tilapia guineensis | present | not_present | present
Tilapia zillii | present | present | present
Fundulus rubrifrons | not_present | present | present
Eutrigla gurnardus | present | present | not_present
Sprattus sprattus | present | not_present | not_present
Я думаю, что, возможно, можно использовать функцию распространения или функцию ifelse, но я действительно не знаю, как ее реализовать. Большое спасибо за любой ответ
Комментарии:
1. Посмотрите
melt
иdcast
в пакете «data.table» (илиpivot_longer
иpivot_wider
в «tidyverse»). Основная идея заключается в том, чтобы сначала преобразовать данные в длинный формат, а затем перейти от длинного формата к новому широкому формату.
Ответ №1:
Здесь есть опция с is.na
. Перебирайте столбцы набора данных с lapply
помощью , создайте логический вектор с is.na
помощью, преобразуйте его в числовой индекс, замените значения вектором строк и привяжите их к столбцу transmute
ed ‘Species_name’, созданному с помощью coalesce
lst1 <- lapply(df1, function(x) c("present", "not_present")[1 is.na(x)])
library(dplyr)
df1 %>%
transmute(Species_name = coalesce(!!! .)) %>%
bind_cols(lst1)
-вывод
# Species_name Country_A Country_B Country_C
#1 Tilapia guineensis present not_present present
#2 Tilapia zillii present present present
#3 Fundulus rubrifrons not_present present present
#4 Eutrigla gurnardus present present not_present
#5 Sprattus sprattus present not_present not_present
Или, если мы хотим сделать это исключительно на tidyverse
, вариант, использующий только dplyr
и более компактно
df1 %>%
mutate(Species_name = coalesce(!!! .),
across(starts_with('Country'),
~c("present", "not_present")[1 is.na(.)]))
# Country_A Country_B Country_C Species_name
#1 present not_present present Tilapia guineensis
#2 present present present Tilapia zillii
#3 not_present present present Fundulus rubrifrons
#4 present present not_present Eutrigla gurnardus
#5 present not_present not_present Sprattus sprattus
данные
df1 <- structure(list(Country_A = c("Tilapia guineensis", "Tilapia zillii",
NA, "Eutrigla gurnardus", "Sprattus sprattus"), Country_B = c(NA,
"Tilapia zillii", "Fundulus rubrifrons", "Eutrigla gurnardus",
NA), Country_C = c("Tilapia guineensisi", "Tilapia zillii",
"Fundulus rubrifrons",
NA, NA)), class = "data.frame", row.names = c(NA, -5L))
Ответ №2:
Используя некоторые tidyverse
функции и разумно изменяя данные, вы можете получить:
library(dplyr)
library(tidyr)
#Code
newdf <- df %>% pivot_longer(everything()) %>%
select(value) %>%
filter(!is.na(value)) %>%
filter(!duplicated(value)) %>%
left_join(
df %>% mutate(id=row_number()) %>%
pivot_longer(-id) %>%
filter(!is.na(value)) %>% mutate(Val='present')) %>%
pivot_wider(names_from = name,values_from=Val,values_fill='not_present',
names_sort=T) %>%
select(-id) %>% rename(Species=value)
Вывод:
# A tibble: 5 x 4
Species Country_A Country_B Country_C
<chr> <chr> <chr> <chr>
1 Tilapia guineensis present not_present present
2 Tilapia zillii present present present
3 Fundulus rubrifrons not_present present present
4 Eutrigla gurnardus present present not_present
5 Sprattus sprattus present not_present not_present
Некоторые используемые данные:
#Data
df <- structure(list(Country_A = c("Tilapia guineensis", "Tilapia zillii",
NA, "Eutrigla gurnardus", "Sprattus sprattus"), Country_B = c(NA,
"Tilapia zillii", "Fundulus rubrifrons", "Eutrigla gurnardus",
NA), Country_C = c("Tilapia guineensis", "Tilapia zillii", "Fundulus rubrifrons",
NA, NA)), row.names = c(NA, -5L), class = "data.frame")
Комментарии:
1. Не могли бы вы немного рассказать о шагах в вашем решении?
2. @A5C1D2H2I1M1N2O1R2T1 По сути, это изменение формы на длинную, затем фильтрация для сохранения уникальных значений, затем слияние и, наконец, изменение формы на широкую!
Ответ №3:
Как упоминалось в комментариях, к этому можно подойти с melt
помощью решения dcast
(или pivot_longer
pivot_wider
). Вот две альтернативы:
melt
dcast
library(data.table)
melt(as.data.table(df), measure = names(df), na.rm = TRUE, value.name = "Species_Name")[
, ind := "present"][
, dcast(.SD, Species_Name ~ variable, value.var = "ind", fill = "not_present")]
# Species_Name Country_A Country_B Country_C
# 1: Eutrigla gurnardus present present not_present
# 2: Fundulus rubrifrons not_present present present
# 3: Sprattus sprattus present not_present not_present
# 4: Tilapia guineensis present not_present present
# 5: Tilapia zillii present present present
pivot_longer
pivot_wider
library(dplyr)
library(tidyr)
df %>%
pivot_longer(everything(), values_drop_na = TRUE, values_to = "Species_Name") %>%
mutate(ind = "present") %>%
pivot_wider(names_from = name, values_from = ind, values_fill = "not_present")
# # A tibble: 5 x 4
# Species_Name Country_A Country_C Country_B
# <chr> <chr> <chr> <chr>
# 1 Tilapia guineensis present present not_present
# 2 Tilapia zillii present present present
# 3 Fundulus rubrifrons not_present present present
# 4 Eutrigla gurnardus present not_present present
# 5 Sprattus sprattus present not_present not_present