Связывание столбцов двух кадров данных разной длины в R tidyverse с сгруппированными векторами

Я пытаюсь связать столбцы с двумя кадрами данных: первый представляет собой временной ряд с многочисленными столбцами и ~ 10 000 строк. Второй является производной первого с коэффициентами корреляции среди других соответствующих векторов.

Очевидно, что второй df намного короче первого. Оба dfs имеют группирующие столбцы species и region.

Цель: я хотел бы добавить результаты более короткого 2-го df к первому, совпадающие по столбцам species и region.

Я пробовал merge, full_join и другие join функции, но они либо приводят к NAs, либо добавляют строки в первый df. Как бы мне сопоставить и объединить эти dfs во вселенной tidy?

Ниже приведен минимальный воспроизводимый пример dfs и желаемого результата:

set.seed(123)

ebird <- data.frame(
  
  region = c("one", "one", "one", "one", "one",
             "one", "one", "one", "one", "one",
             "one", "one", "one", "one", "one",
             "two", "two", "two", "two", "two",
             "two", "two", "two", "two", "two",
             "two", "two", "two", "two", "two",
             "three", "three", "three", "three", "three",
             "three", "three", "three", "three", "three",
             "three", "three", "three", "three", "three"),
  Species = c("A", "A", "A", "A", "A",
              "B", "B", "B", "B", "B",
              "C", "C", "C", "C", "C",
              "A", "A", "A", "A", "A",
              "B", "B", "B", "B", "B",
              "C", "C", "C", "C", "C",
              "A", "A", "A", "A", "A",
              "B", "B", "B", "B", "B",
              "C", "C", "C", "C", "C"),
  value = sample(seq(from = 1, to = 45, by = 1), replace = TRUE), # abundance
  date = seq(from = 1, to = 5, by = 1)
  
) 

cor <- data.frame(
  
  region = c("one", "one", "one",
             "two", "two", "two",
             "three", "three", "three"),
  Species = c("A", "B", "C",
              "A", "B", "C",
              "A", "B", "C"),
  rho = sample(seq(from = -1, to = 1, by = 0.1), size = 9, replace = TRUE),
  date_max_value = sample(seq(from = 1, to = 5, by = 1), size = 9, replace = TRUE) # date of max abundance (value)

)

desired_output <- data.frame(
  
  region = c("one", "one", "one", "one", "one",
             "one", "one", "one", "one", "one",
             "one", "one", "one", "one", "one",
             "two", "two", "two", "two", "two",
             "two", "two", "two", "two", "two",
             "two", "two", "two", "two", "two",
             "three", "three", "three", "three", "three",
             "three", "three", "three", "three", "three",
             "three", "three", "three", "three", "three"),
  Species = c("A", "A", "A", "A", "A",
              "B", "B", "B", "B", "B",
              "C", "C", "C", "C", "C",
              "A", "A", "A", "A", "A",
              "B", "B", "B", "B", "B",
              "C", "C", "C", "C", "C",
              "A", "A", "A", "A", "A",
              "B", "B", "B", "B", "B",
              "C", "C", "C", "C", "C"),
  value = sample(seq(from = 1, to = 45, by = 1), replace = TRUE), # abundance
  date = seq(from = 1, to = 5, by = 1),
  rho = c(rep(-0.6, 5), rep(-0.3, 5), rep(0.1, 5), rep(-0.2, 5), rep(0.7, 5),
          rep(-1.0, 5), rep(-0.5, 5), rep(1.0, 5), rep(0.4, 5)),
  date_max_value = c(rep(1, 5), rep(2, 5), rep(4, 5), rep(4, 5), rep(3, 5),
                     rep(1, 5), rep(2, 5), rep(1, 5), rep(2, 5))
  
) 

РЕДАКТИРОВАТЬ Добавление dput(head(df1)) и dput(head(df2)), чтобы читатели понимали структуру данных. Примечание. Я пытаюсь использовать left_join в столбце Species, а не в столбце species — я понимаю, что это может создать некоторую путаницу, учитывая, что в моем примере с игрушкой мой вид не был написан с заглавной буквы:

dput(head(ebird))
structure(list(species = c("Mallard", "Mallard", "Mallard", "Mallard", 
"Mallard", "Mallard"), week = structure(c(19255, 19262, 19276, 
19283, 19290, 19304), class = "Date"), median = c(3.28408646583557, 
2.67390370368958, 6.20513391494751, 16.557181596756, 26.7760531902313, 
118.688171863556), region = c("Adams", "Adams", "Adams", "Adams", 
"Adams", "Adams"), month = c(9, 9, 10, 10, 10, 11), lower = c(2.58288896083832, 
2.33652949333191, 5.62750267982483, 15.5113918781281, 24.3405115604401, 
102.083569049835), upper = c(3.94177603721619, 2.92097306251526, 
7.13815760612488, 17.6045758724213, 29.9772963523865, 141.712877750397
), Date = structure(c(19255, 19262, 19276, 19283, 19290, 19304
), class = "Date"), week1 = c(38, 39, 41, 42, 43, 45), Species = c("MALL", 
"MALL", "MALL", "MALL", "MALL", "MALL"), survey = c(0, 0, 0, 
0, 0, 100), year = c(2022, 2022, 2022, 2022, 2022, 2022), day = c(20L, 
27L, 11L, 18L, 25L, 8L), Date1 = structure(c(19255, 19262, 19276, 
19283, 19290, 19304), class = "Date"), difference = c(3.28408646583557, 
2.67390370368958, 6.20513391494751, 16.557181596756, 26.7760531902313, 
18.6881718635559), max_survey = c(500, 500, 500, 500, 500, 500
), max_ebird = c(231.35857963562, 231.35857963562, 231.35857963562, 
231.35857963562, 231.35857963562, 231.35857963562), max_ebird_upper = c(262.414058685303, 
262.414058685303, 262.414058685303, 262.414058685303, 262.414058685303, 
262.414058685303), max_ebird_lower = c(211.088241577148, 211.088241577148, 
211.088241577148, 211.088241577148, 211.088241577148, 211.088241577148
), scaled_ebird = c(0.0141947900570961, 0.0115574002394934, 0.0268204184375627, 
0.0715650209420927, 0.115733997124301, 0.513005275406189), scaled_ebird_upper = c(0.0150212075411071, 
0.0111311607203873, 0.0272018871316847, 0.0670870149283174, 0.114236624754684, 
0.540035387053498), scaled_ebird_lower = c(0.0122360627078999, 
0.011068970378807, 0.0266594796459475, 0.0734829745239929, 0.115309651445195, 
0.483606136879613), scaled_survey = c(0, 0, 0, 0, 0, 0.2), zscaled_ebird = c(-1.15368075571164, 
-1.16038986114502, -1.12156314025646, -1.00773989965177, -0.895380961995726, 
0.115214769380754), zscaled_ebird_upper = c(-1.14916660942026, 
-1.15919230741443, -1.11777371864876, -1.01497900584015, -0.893461766987318, 
0.203936283432415), zscaled_ebird_lower = c(-1.15213092209424, 
-1.15506773303076, -1.11583657969332, -0.998012352409944, -0.892761860089624, 
0.0340004185595489), zscaled_survey = c(-0.639688641399654, -0.639688641399654, 
-0.639688641399654, -0.639688641399654, -0.639688641399654, -0.0156021619853574
)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"
))
> dput(head(cor))
structure(list(Date1 = structure(c(19255, 19241, 19234, 19234, 
19234, 19234), class = "Date"), survey = c(0, 0, 0, 0, 0, 0), 
    Species = c("ABDU ", "ABDU ", "ABDU ", "ABDU ", "ABDU ", 
    "ABDU "), region = c(" Adams", " Appanoose/Lucas", " Bremer", 
    " Buena Vista", " Butler", " Calhoun"), Parameter1 = c("scaled_ebird", 
    "scaled_ebird", "scaled_ebird", "scaled_ebird", "scaled_ebird", 
    "scaled_ebird"), Parameter2 = c("scaled_survey", "scaled_survey", 
    "scaled_survey", "scaled_survey", "scaled_survey", "scaled_survey"
    ), rho = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_), CI = c(0.95, 0.95, 0.95, 0.95, 0.95, 0.95), CI_low = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), CI_high = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), S = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), p = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), Method = c("NA correlation", 
    "NA correlation", "NA correlation", "NA correlation", "NA correlation", 
    "NA correlation"), n_Obs = c(0L, 0L, 0L, 0L, 0L, 0L), state = c("IA", 
    "IA", "IA", "IA", "IA", "IA")), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

Это была моя первая мысль. Я получаю правильное количество строк, используя left_join, но все столбцы из df2 заполнены NA

Nick 13.06.2024 21:56

С помощью этих игрушечных данных или только с вашими реальными наборами данных?

Seth 13.06.2024 21:57

Только реальные данные. Единственная разница между реальными и игрушечными данными заключается в том, что в реальных данных есть NA... и больше столбцов.

Nick 13.06.2024 22:00

Запустите dput(head(df1)) и dput(head(df2)) на своих реальных данных и добавьте результаты в кодовый блок вашего вопроса. Это поможет исключить проблемы. Измените имена df в dput() на имена ваших реальных данных, если они отличаются от ваших реальных данных.

L Tyrone 13.06.2024 22:03

@Сет, я думаю, ты имеешь в виду dplyr::left_join

Jon Spring 13.06.2024 22:34

Да, спасибо, что поймали это!

Seth 13.06.2024 22:34

Я вижу, что ebird$Species выглядит как «MALL», но cor$Species выглядит как «ABDU» с пробелом в конце. Они не присоединятся (получив NA), если этот шаблон распространится на остальные данные. Попробуйте cor$Species = stringr::str_trim(cor$Species) удалить все начальные/конечные пробелы.

Jon Spring 13.06.2024 22:37

База R trimws() тоже подойдет.

Ifeanyi Idiaye 13.06.2024 22:41

Все еще не повезло. Все столбцы из df2 (cor) по-прежнему заполняются NA после добавления stringr::str_trim(Species) в конвейерный рабочий процесс в cor df. Как вы ставите диагноз? И будет ли это как-то связано с NA в df2?

Nick 13.06.2024 23:35

Подожди секунду - подожди. Я не пробовала str_trim(region).

Nick 13.06.2024 23:36

Успех. Загадочная проблема, но легко решаемая. Спасибо вам всем.

Nick 13.06.2024 23:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В предоставленном вами образце реальных данных нет соответствующих записей, поэтому я изменил значения cor$Species на «MALL», сохранив конечный пробел, как в исходных данных.

Я также отметил, что cor$region имеет ведущий пробел.

Попробуй это:

ebird %>%
  inner_join(
    cor %>%
      mutate(
        region = str_trim(region),
        Species = str_trim(Species)
      ),
    by = c("region", "Species")
  )

Он удаляет начальные и конечные пробелы в ключевых столбцах cor.

Это дает приемлемые результаты для данных об игрушках (хотя значения в столбце value, похоже, не совпадают между ebird и desired_output).

С измененными реальными данными он дает только 6 строк (соответствующих строкам в ebird) и выбирает соответствующие значения из cor).

Если это не поможет, возможно, вы могли бы предоставить подмножество реальных данных, в которых есть совпадения между записями?

Спасибо датавуки и Джону Спрингу. Проблема заключалась в том, что и Species, и region имели пробелы и не могли соответствовать исходному набору данных. Пространства возникли в результате корреляционного анализа, в результате которого был создан столбец, объединяющий значения видов и регионов (например, MALL – Адамс). Я использовал dplyr::separate, чтобы «воссоздать» эти столбцы и значения, но не смог обрезать пробелы, что вызвало проблему привязки столбцов.

Nick 14.06.2024 15:46

Другие вопросы по теме

Невозможно преобразовать данные столбца и сохранить их в одном новом столбце в пандах фрейма данных
Каков наиболее эффективный способ заполнения нескольких столбцов значениями из других столбцов таким образом, чтобы их можно было соединить с суффиксом?
Создание таблицы частот для каждого столбца в фрейме данных с помощью цикла и сохранение результатов в списке
Объедините две таблицы, если заданное значение переменной является частью другой переменной
Табуляция столбца в data.frame, игнорируя порядок элементов в нем в R
Как я могу объединить два кадра данных на основе последней даты каждой группы?
График временных рядов с цветовой кодировкой на основе знака значения
Сводная таблица панд на несколько столбцов
Замените отсутствующие строки в фрейме данных A вместе с соответствующими значениями данными из кадра данных B
Привяжите каждый фрейм данных в списке к каждому фрейму данных другого списка