Как заполнить столбец в фрейме данных на основе условий из фрейма данных различной длины? - PullRequest
0 голосов
/ 02 июня 2019

Итак, у меня есть два фрейма данных, первый из которых похож на этот, с названием различных видов морских рыб (одни и те же виды повторяются на всем фрейме данных с общим количеством записей 74610), их соответствующие БИН (своего рода серийный номер). номер, который присваивается виду на основе алгоритма кластеризации) и пустой столбец (сорт), который я хочу заполнить на основе условий из второго кадра данных:

dataframe1

         species               BIN        grade
1.  Tilapia guineensis |  BOLD:AAL5979  |  NA

2.     Tilapia zillii  |  BOLD:AAB9042  |  NA

3. Fundulus rubrifrons |  BOLD:AAI7245  |  NA

4.  Eutrigla gurnardus |  BOLD:AAC0262  |  NA

5.   Sprattus sprattus |  BOLD:AAE9187  |  NA

6.        Gadus morhua |  BOLD:ACF1143  |  NA

Второй кадр данных имеет вид (повторяется только один раз на этот раз, всего 7633 записи) и количество BIN, назначенных каждому виду:

dataframe2

        species             bin_per_species       BIN

1. Abalistes filamentosus |       1        |  BOLD:AAD4738

2. Abalistes stellaris    |       2        |  BOLD:AAD4739,BOLD:ACK7828 

3. Abalistes stellatus    |       2        |  BOLD:AAD4739,BOLD:ACK7828 

4. Ablabys binotatus      |       1        |  BOLD:AAF8834   

5. Ablennes hians         |       2        |  BOLD:AAC1231,BOLD:AAB9824

6. Abramis brama          |       1        |  BOLD:AAC8592               

Что я хочу сделать, так это заполнить столбец оценки в dataframe1, учитывая количество BIN, присвоенных каждому виду в dataframe2. Например, если в dataframe2 вид имеет bin_per_species == 1, я хочу присвоить оценку «A», но если, например, вид в dataframe2 имеет bin_per_species> 1, я хочу присвоить оценку «C».

Я пытался использовать функцию% in%, поскольку не могу использовать "==", поскольку они имеют разную длину.

неудачная попытка

dataframe1$grade[(as.character(dataframe1$species)%in%as.character(dataframe2$species))[dataframe2$bin_per_species==1]]="A"

Я бы ожидал, что dataframe1 будет заполнен в соответствии с условием, но в результате я просто заполняю каждую ячейку оценкой «A», когда пытаюсь выполнить приведенный выше код. Извините, если я не смог представить свою проблему, но заранее благодарю за любые ответы.

Ответы [ 3 ]

0 голосов
/ 02 июня 2019

Я упростил вашу проблему, чтобы я смог ее протестировать. Пожалуйста, сообщите мне, если это не сработает для вас.Я оставил мои простые кадры данных, чтобы вы могли видеть мой процесс.

df1 <- data.frame(
  species <- c('a', 'b', 'c', 'd'),
  grade <- c(NA, NA, NA, NA)
)
colnames(df1) <- c('species', 'grade')

df2 <- data.frame(
  species <- c('a', 'b', 'c', 'd'),
  bin_per_species <- c(1, 2, 2, 1)
)
colnames(df2) <- c('species', 'bin_per_species')

df1[species %in% df2[which(df2[, 'bin_per_species'] == 2), 'species'], 'grade'] <- 'A'
0 голосов
/ 03 июня 2019

К сожалению, ваши два фрейма данных не очень полезны, но я думаю, что можно работать в обратном направлении со второго фрейма данных, чтобы получить более репрезентативные данные.На основании вашего комментария первый фрейм данных может содержать один и тот же species с разными BIN с.Если это так, то мы можем просто разделить второй кадр данных, чтобы получить df1:

# A tibble: 9 x 3
  species                BIN          grade
  <chr>                  <chr>        <int>
1 Abalistes filamentosus BOLD:AAD4738    NA
2 Abalistes stellaris    BOLD:AAD4739    NA
3 Abalistes stellatus    BOLD:AAD4739    NA
4 Ablabys binotatus      BOLD:AAF8834    NA
5 Ablennes hians         BOLD:AAC1231    NA
6 Abramis brama          BOLD:AAC8592    NA
7 Abalistes stellaris    BOLD:ACK7828    NA
8 Abalistes stellatus    BOLD:ACK7828    NA
9 Ablennes hians         BOLD:AAB9824    NA

Второй кадр данных df2 остается тем же.

Использование одного кадра данных

Если я правильно понял проблему, вам действительно даже не нужен второй кадр данных.Вместо этого вы можете сделать что-то вроде этого, который группирует по species и дает каждой группе оценку в зависимости от ее размера n():

df1 %>% 
    group_by(species) %>% 
    mutate(grade = ifelse(n() == 1, "A", "C"))

#### OUTPUT ####

# A tibble: 9 x 3
# Groups:   species [6]
  species                BIN          grade
  <chr>                  <chr>        <chr>
1 Abalistes filamentosus BOLD:AAD4738 A    
2 Abalistes stellaris    BOLD:AAD4739 C    
3 Abalistes stellatus    BOLD:AAD4739 C    
4 Ablabys binotatus      BOLD:AAF8834 A    
5 Ablennes hians         BOLD:AAC1231 C    
6 Abramis brama          BOLD:AAC8592 A    
7 Abalistes stellaris    BOLD:ACK7828 C    
8 Abalistes stellatus    BOLD:ACK7828 C    
9 Ablennes hians         BOLD:AAB9824 C    

Использование двух фреймов данных

Если,по какой-то причине вам нужно использовать df1 и df2, я думаю, что самый простой подход - это объединить два кадра данных в species, а затем изменить grade в соответствии со значениями bin_per_species:

full_join(df1, df2, by = "species") %>% 
    mutate(grade = case_when(bin_per_species == 1 ~ "A",
                             bin_per_species == 2 ~ "B",
                             bin_per_species  > 2 ~ "C",
                             )) %>% 
    select(1:3)

#### OUTPUT ####

# A tibble: 9 x 3
  species                BIN.x        grade
  <chr>                  <chr>        <chr>
1 Abalistes filamentosus BOLD:AAD4738 A    
2 Abalistes stellaris    BOLD:AAD4739 B    
3 Abalistes stellatus    BOLD:AAD4739 B    
4 Ablabys binotatus      BOLD:AAF8834 A    
5 Ablennes hians         BOLD:AAC1231 B    
6 Abramis brama          BOLD:AAC8592 A    
7 Abalistes stellaris    BOLD:ACK7828 B    
8 Abalistes stellatus    BOLD:ACK7828 B    
9 Ablennes hians         BOLD:AAB9824 B    

Я включил case_when() на случай, если у вас больше, чем просто две степени «А» и «С».Вы также можете использовать его в решении "один кадр данных".Если у вас действительно есть только эти две оценки, вы можете упростить вещи с помощью ifelse():

full_join(df1, df2, by = "species") %>% 
    mutate(grade = ifelse(bin_per_species == 1, "A", "C")) %>% 
    select(1:3)
0 голосов
/ 02 июня 2019

приветствуется

Пожалуйста, проверьте, работает ли это, и посмотрите на функцию dput ().

library(tidyverse)

df <- tribble(~species,~BIN,
              "A",1,
              "B",2,
              "B",3,
              "B",4)

df %>% 
  group_by(species) %>% 
  summarise(count_bins = n()) %>% 
  mutate(grade = if_else(count_bins > 1,
                         "C",
                         "A")) %>% 
  right_join(df)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...