Как удалить NAs фрейма данных, изменив расположение данных?

#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