Подмножественный фрейм данных, основанный на значениях во втором фрейме данных - PullRequest
0 голосов
/ 27 августа 2018

У меня есть один фрейм данных, df, который имеет два столбца как таковые:

> head(df1[,c(10,11)])
       ColA      ColB
1        12        20
2         7         5
3        32        38
4        37        46
5        15        15
6         4         4

У меня есть второй фрейм данных, также с 2 столбцами с совпадающими именами. Вместо этого есть только два числа:

> head(df2)
       ColA      ColB
1        50        30

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

colA_vector <- df1[df1$colA < 50,]
colB_vector <- df1[df1$ColB < 30,]

Как я могу сделать это более универсальным способом? Я не хочу ничего жестко кодировать. Имя столбца «ColA» или «ColB» может быть любым (поэтому решения, требующие этих имен столбцов, на самом деле не будут работать).

Спасибо.

Ответы [ 5 ]

0 голосов
/ 27 августа 2018

Использование dplyr:

df1 %>%
  filter(df1[,1] < df2[,1])

  ColA ColB
1   12   20
2    7    5
3   32   38
4   37   46
5   15   15
6    4    4

df1 %>%
  filter(df1[,2] < df2[,2])

  ColA ColB
1   12   20
2    7    5
3   15   15
4    4    4

Подмножество на основе обоих столбцов одновременно:

df1 %>%
  filter(df1[,1] < df2[,1] & df1[,2] < df2[,2])

  ColA ColB
1   12   20
2    7    5
3   15   15
4    4    4
0 голосов
/ 27 августа 2018

Вы можете попробовать функцию tidyverse. Результатом является список отфильтрованных данных.

foo <- function(x, y, ColA, ColB){
  require(tidyverse)
  var1 <- quo_name(ColA)
  var2 <- quo_name(ColB)
  x %>%
  select(a=!!var1, b=!!var2) %>% 
  mutate(colA_vector= a < y[[ColA]]) %>% 
  mutate(colB_vector= b < y[[ColB]]) %>% 
  gather(k, v, -a, -b) %>% 
  filter(v) %>%
  split(.$k) %>% 
  map(~select(.,-v,-k))
}
foo(df1, df2, "ColA", "ColB")
$colA_vector
   a  b
1 12 20
2  7  5
3 32 38
4 37 46
5 15 15
6  4  4

$colB_vector
    a  b
7  12 20
8   7  5
9  15 15
10  4  4
0 голосов
/ 27 августа 2018

В базе R мы могли бы сделать:

nms <- intersect(names(df1), names(df2))
df1[do.call(`&`, Map(`<`, df1[nms], df2[nms])),]
#   ColA ColB
# 1   12   20
# 2    7    5
# 5   15   15
# 6    4    4

Или просто df1[do.call('&', Map('<', df1, df2)),], если оба data.frames имеют одинаковый порядок столбцов и одинаковые имена.

Использование пакета fuzzyjoin может быть более читабельным, однако:

library(fuzzy_join)
fuzzy_semi_join(df1, df2, match_fun = `<`)
#   ColA ColB
# 1   12   20
# 2    7    5
# 5   15   15
# 6    4    4

Данные

df1 <- read.table(text="
ColA      ColB
1        12        20
2         7         5
3        32        38
4        37        46
5        15        15
6         4         4",h=T,strin=F)

df2 <- read.table(text="ColA      ColB
1        50        30",h=T,strin=F)
0 голосов
/ 27 августа 2018

Если вы не хотите использовать пакет fuzzyjoin join или создать свою собственную функцию, вы можете просто повторить второй кадр данных.

df1 <- data.frame("ColA" = c(12, 7, 32),
             "ColB" = c(20, 5, 38))
df2 <- data.frame("ColA" = 50,
              "ColB" = 30)

n <- nrow(df1)
df2_new <- do.call("rbind", replicate(n, df2, simplify = FALSE))
df1_which <- as.data.frame(df1 < df2_new)

colA_vector <- df1[df1_which$ColA, "ColA"]
colB_vector <- df1[df1_which$ColB, "ColB"]
0 голосов
/ 27 августа 2018

Создайте функцию, если мы хотим выполнить одну и ту же задачу несколько раз

f1 <- function(dat1, dat2, colName) {
        dat1[dat1[[colName]] < dat2[[colName]],]
  }

f1(df1, df2, "ColA")
#  ColA ColB
#1   12   20
#2    7    5
#3   32   38
#4   37   46
#5   15   15
#6    4    4

f1(df1, df2, "ColB")
#  ColA ColB
#1   12   20
#2    7    5
#5   15   15
#6    4    4

данные

df1 <- structure(list(ColA = c(12L, 7L, 32L, 37L, 15L, 4L), ColB = c(20L, 
5L, 38L, 46L, 15L, 4L)), class = "data.frame", row.names = c(NA, 
-6L))

df2 <- structure(list(ColA = 50L, ColB = 30L), 
     class = "data.frame", row.names = "1")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...