Объединение двух кадров данных на основе первых двух столбцов с одинаковой информацией, расположенной по-разному в R - PullRequest
0 голосов
/ 01 ноября 2018

Я хочу объединить два фрейма данных на основе первых двух столбцов и их значений, однако эти значения в этих столбцах можно переключать между столбцами в соответствии с набором данных. Поэтому функции merge или left_join в пакете dplyr не могут видеть, что парная информация одинакова.

Для лучшего объяснения я определил здесь два гипотетических набора данных:

tree.dat1 = data.frame(tree1 = factor(c(rep(33,3),rep(22,2),11)),
+                       tree2 = factor(c(22,11,44,11,44,44)),
+                       value = c(0.02, rep(0.03,3), rep(0.01,2)))

> tree.dat1
   tree1 tree2 value
1    33    22  0.02
2    33    11  0.03
3    33    44  0.03
4    22    11  0.03
5    22    44  0.01
6    11    44  0.01

tree.dat2 = data.frame(tree1 = factor(c(rep(11,3),rep(33,2),22)),
+                        tree2 = factor(c(22,33,44,22,44,44)),
+                        value1 = c(rep(3,0.05),0.02,rep(0.03,2)))
> tree.dat2
  tree1 tree2 value1
1    11    22   0.02
2    11    33   0.03
3    11    44   0.03
4    33    22   0.02
5    33    44   0.03
6    22    44   0.03

Как видите, пары первых двух столбцов одинаковы, однако порядок их различен. Поэтому я хочу создать новый набор данных, используя эту информацию в первых двух столбцах и сохранив оба третьих столбца в этих наборах данных.

Итак:

> tree.dat3 = left_join(tree.dat1,tree.dat2, by = c("tree1","tree2"))
> tree.dat3
   tree1 tree2 value value1
1    33    22  0.02   0.02
2    33    11  0.03     NA
3    33    44  0.03   0.03
4    22    11  0.03     NA
5    22    44  0.01   0.03
6    11    44  0.01   0.03

В конце у меня есть два значения NA, однако, когда я проверяю попарные таблицы, я вижу, что информация для попарно 33 - 11 (или 22 - 11) дается в наборе данных tree.dat1.

Итак, ожидаемый результат:

   tree1 tree2 value value1
1    33    22  0.02   0.02
2    33    11  0.03   0.03
3    33    44  0.03   0.03
4    22    11  0.03   0.02
5    22    44  0.01   0.03
6    11    44  0.01   0.03

Так что, вероятно, я ищу какой-то другой способ объединить два кадра данных, чтобы проверить попарную информацию, а не уровни факторов в двух столбцах. Потому что 33 - 11 и 11 - 33 - то же самое, но значения отличаются в третьих столбцах. Я хотел бы знать подходящий способ сделать это для больших наборов данных. Есть предложения?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Вот базовое решение R. Факторы могут осложнить вашу проблему. Если вам нужно их использовать, возможно, конвертируйте символы в ваш проект.

tree.dat1 = data.frame(tree1 = (c(rep(33,3),rep(22,2),11)),
                       tree2 = (c(22,11,44,11,44,44)),
                       value = c(0.02, rep(0.03,3), rep(0.01,2)))

tree.dat2 = data.frame(tree1 = (c(rep(11,3),rep(33,2),22)),
                        tree2 = (c(22,33,44,22,44,44)),
                        value1 = c(rep(3,0.05),0.02,rep(0.03,2)))

tree.dat1$id=apply(tree.dat1[,1:2], 1, function(x)paste(sort(x), collapse="-"))
tree.dat2$id=apply(tree.dat2[,1:2], 1, function(x)paste(sort(x), collapse="-"))

tree.dat3 = left_join(tree.dat1,tree.dat2[,3:4], by = "id")[,-4]


> tree.dat3
  tree1 tree2 value value1
1    33    22  0.02   0.02
2    33    11  0.03   0.03
3    33    44  0.03   0.03
4    22    11  0.03   0.02
5    22    44  0.01   0.03
6    11    44  0.01   0.03
0 голосов
/ 01 ноября 2018

Поскольку порядок объединения не имеет значения, давайте создадим столбец TreeID, в котором мы сортируем tree1 и tree2, чтобы пары чисел всегда приходились в одном порядке.

Это проще, если ваши данные не закодированы как factor, потому что взятие min/max фактора не работает, и вам нужно привести к символу, а затем к числовому, чтобы заставить его работать нормально. Если вам нужно сделать это с вашими исходными данными, as.numeric(as.character(tree.dat1$tree)) поможет. Вы можете взять максимум вектора character без преобразования в numeric, но я предпочитаю этого не делать, потому что max("11","2") работает не так, как вы могли бы ожидать.

library(tidyverse)
library(stringr)

tree.dat1 = data.frame(tree1 = c(rep(33,3),rep(22,2),11),
                       tree2 = c(22,11,44,11,44,44),
                       value = c(0.02, rep(0.03,3), rep(0.01,2)))

tree.dat2 = data.frame(tree1 = c(rep(11,3),rep(33,2),22),
                       tree2 = c(22,33,44,22,44,44),
                        value1 = c(rep(3,0.05),0.02,rep(0.03,2)))

Создайте TreeID, объединив минимальное и максимальное значения tree1 и tree2. Мы используем rowwise() для получения максимального и минимального значения для каждой строки, а не для каждого столбца.

tree.dat1 <- tree.dat1 %>% rowwise() %>% 
  mutate(TreeID= str_c(min(tree1, tree2), max(tree1,tree2)))

tree.dat2 <- tree.dat2 %>% rowwise() %>% 
  mutate(TreeID= str_c(min(tree1, tree2), max(tree1,tree2)))

left_join(tree.dat1, tree.dat2, by = "TreeID")


Source: local data frame [6 x 7]
Groups: <by row>

# A tibble: 6 x 7
  tree1.x tree2.x value TreeID tree1.y tree2.y value1
    <dbl>   <dbl> <dbl> <chr>    <dbl>   <dbl>  <dbl>
1      33      22  0.02 2233        33      22   0.02
2      33      11  0.03 1133        11      33   0.03
3      33      44  0.03 3344        33      44   0.03
4      22      11  0.03 1122        11      22   0.02
5      22      44  0.01 2244        22      44   0.03
6      11      44  0.01 1144        11      44   0.03

Чтобы точно соответствовать желаемому выводу:

left_join(tree.dat1, tree.dat2, by = "TreeID") %>% select(-tree1.y, -tree2.y, -TreeID) %>% 
  rename(tree1 = tree1.x, tree2 = tree2.x)

  tree1 tree2 value value1
  <dbl> <dbl> <dbl>  <dbl>
1    33    22  0.02   0.02
2    33    11  0.03   0.03
3    33    44  0.03   0.03
4    22    11  0.03   0.02
5    22    44  0.01   0.03
6    11    44  0.01   0.03
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...