r - сопоставление двух информационных кадров и вставка строк из одного в другой при условии - PullRequest
0 голосов
/ 16 мая 2018

Недавно я пытался произвести определенный вывод, используя 2 кадра данных, но, похоже, моего опыта работы с R по-прежнему недостаточно для этого. Я провел много часов, но не могу найти ответ, как это сделать. Любая помощь по следующему заданию приветствуется.

У меня есть два набора данных base_df и compare_df. Определенные элементы (ячейки) из compare_df должны быть вставлены в base_df с использованием следующих правил:

a) элемент из id столбца из base_df и элемент из id из compare_df должны быть равны

b) если число от xx, yy или zz, после того, как символ отделен, используя разделитель _ для ex. «1.5_2.5» можно сохранить в 2 отдельных переменных, таких как val1 = 1,5 и val2 = 2,5, поэтому:
если (compare_df$val1 > base_df$var1 & compare_df$val1 < lead(base_df$var1)) & (compare_df$val2 > base_df$var2 & compare_df$val2 < lead(base_df$var2)), то вставьте значения val1 и val2 из compare_df между строками 1 и 2 в base_df.

в) использовать имя переменной, для которой был выполнен обмен, в данном случае для ex. создайте новую переменную, скажем, ind, и присвойте значение этой переменной для вновь созданной строки 2 в base_df, равное "xx".

Примечание: compare_df имеет много столбцов, таких как xx,yy and zz, для которых также необходимо выполнить процесс. Таким образом, условие проверяется для всех столбцов в compare_df, кроме идентификатора.

В основном, каждая информация строки из compare_df должна сравниваться со всеми строками в base_df и проверять, выполняются ли условия. Там может быть несколько совпадений. Исходный порядок строк должен быть сохранен, поэтому arrange нельзя использовать, так как var1 и var2 не увеличиваются с номером строки. Может быть, это можно сделать с помощью функций apply?

Ниже приведены упрощенные примеры:

base_df <- data.frame(id = c("a", "a", "a", "a", "a", "b", "b", "b", "b", "b"), 
                      var1 = c(1,3,5,-7,-9,11,13,15,17,19),
                      var2 = c(2,4,6,8,-10,12,14,16,18,20))

compare_df <- data.frame(id = c("a", "b"), 
                     xx = c("1.5_2.5", "17.5_18.5"),
                     yy = c("3.5_2.5", "12.5_18.5"),
                     zz = c("3.5_4.5", "15.5_16.5"))

# desired
final_df <- data.frame(
  id = c("a", "a", "a", "a", "a", "a", "a", "b", "b", "b", "b", "b", "b", "b"),
  ind = c("org", "xx", "org", "zz", "org", "org", "org", "org", "org", "org", "zz", "org", "xx", "org"),
  var1 = c(1, 1.5, 3, 3.5, 5, -7, -9, 11, 13, 15, 15.5, 17, 17.5, 19),
  var2 = c(2, 2.5, 4, 4.5, 6, 8, -10, 12, 14, 16, 16.5, 18, 18.5, 20))

Simplified example result below

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Решение с использованием . Предполагая, что строки из исходного base_df называются old в столбце ind в новом фрейме данных. Не совсем понятно, каковы ваши условия фильтрации, но я попытался соответствовать вашему ожидаемому результату. new_df - конечный результат.

library(tidyverse)

compare_df2 <- compare_df %>%
  gather(ind, value, -id) %>%
  separate(value, into = c("var1", "var2"), sep = "_", convert = TRUE)

new_df <- base_df %>%
  mutate(ind = "org") %>%
  bind_rows(compare_df2) %>%
  select(id, ind, var1, var2) %>%
  arrange(id, var1, var2) %>%
  filter(var2 > var1) %>%
  filter(row_number() != which(var2 < lag(var2)) - 1)

new_df
#    id ind var1 var2
# 1   a org  1.0  2.0
# 2   a  xx  1.5  2.5
# 3   a org  3.0  4.0
# 4   a  zz  3.5  4.5
# 5   a org  5.0  6.0
# 6   a org  7.0  8.0
# 7   a org  9.0 10.0
# 8   b org 11.0 12.0
# 9   b org 13.0 14.0
# 10  b org 15.0 16.0
# 11  b  zz 15.5 16.5
# 12  b org 17.0 18.0
# 13  b  xx 17.5 18.5
# 14  b org 19.0 20.0
0 голосов
/ 16 мая 2018

Вот возможное решение для аккуратного стиха:

base_df <- data.frame(id = c("a", "a", "a", "a", "a", "b", "b", "b", "b", "b"), 
                      var1 = seq(1,20, by = 2),
                      var2 = seq(2,21, by = 2))

compare_df <- data.frame(id = c("a", "b"), 
                         xx = c("1.5_2.5", "17.5_18.5"),
                         yy = c("3.5_2.5", "12.5_18.5"),
                         zz = c("3.5_4.5", "15.5_16.5"))


# Reshape compare_df to long
compare_df <- gather(compare_df, ind, value, -id)
# Sep the compare_df by "_"
compare_df <- separate(compare_df, col=value, into = c("var1", "var2"), sep = "_")

# Add the "org" column to base_df
base_df$ind <- "org"
# Combine and sort the dfs
final_df2 <- rbind(base_df, compare_df) %>%
  arrange(id, var1)

# I think you wanted to only keep compare_df where var1 was < var2?
final_df2 <- filter(final_df2, var1 < var2)
final_df2

   id var1 var2 ind
1   a    1    2 org
2   a  1.5  2.5  xx
3   a    3    4 org
4   a  3.5  4.5  zz
5   a    5    6 org
6   a    7    8 org
7   b   11   12 org
8   b 12.5 18.5  yy
9   b   13   14 org
10  b   15   16 org
11  b 15.5 16.5  zz
12  b   17   18 org
13  b 17.5 18.5  xx
14  b   19   20 org
...