Условный фильтр с динамической индексацией c столбцов для получения максимального значения между двумя таблицами - PullRequest
0 голосов
/ 18 июня 2020

У меня есть две таблицы ниже

mydata1

| src | des | tier | hop1 | hop2 | hop3 | hop4 | cnt | arvv |
|-----|-----|------|------|------|------|------|-----|------|
| a   | x   | eco  | a    | x    | NA   | NA   | 2   | 8.49 |
| a   | x   | reg  | a    | x    | NA   | NA   | 2   | 8.49 |
| a   | y   | eco  | a    | f    | y    | NA   | 3   | 8.49 |
| a   | y   | reg  | a    | f    | y    | NA   | 3   | 8.49 |
| b   | z   | eco  | b    | g    | z    | NA   | 3   | 8.49 |
| b   | z   | reg  | b    | g    | z    | NA   | 3   | 8.49 |
| b   | m   | eco  | b    | q    | v    | m    | 4   | 8.49 |
| b   | m   | reg  | b    | q    | v    | m    | 4   | 8.49 |
| c   | n   | eco  | c    | e    | a    | n    | 4   | 8.49 |
| c   | n   | reg  | c    | e    | a    | n    | 4   | 8.49 |
| c   | k   | eco  | c    | e    | a    | k    | 4   | 8.49 |
| c   | k   | reg  | c    | e    | a    | k    | 4   | 8.49 |

    structure(list(src = c("a", "a", "a", "a", "b", "b", "b", "b", 
    "c", "c", "c", "c"), des = c("x", "x", "y", "y", "z", "z", "m", 
    "m", "n", "n", "k", "k"), tier = c("eco", "reg", "eco", "reg", 
    "eco", "reg", "eco", "reg", "eco", "reg", "eco", "reg"), hop1 = c("a", 
    "a", "a", "a", "b", "b", "b", "b", "c", "c", "c", "c"), hop2 = c("x", 
    "x", "f", "f", "g", "g", "q", "q", "e", "e", "e", "e"), hop3 = c(NA, 
    NA, "y", "y", "z", "z", "v", "v", "a", "a", "a", "a"), hop4 = c(NA, 
    NA, NA, NA, NA, NA, "m", "m", "n", "n", "k", "k"), cnt = c(2L, 
    2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L), arvv = c(8.49, 8.49, 
    8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49), 
        `max(cutoff)` = c(-2L, -2L, 8L, 8L, -2L, -2L, -32L, -32L, 
        4L, 4L, 4L, 4L)), row.names = c(NA, -12L), class = "data.frame")

mydata2

| tier | hop1 | hop2 | cutoff | landing |
|------|------|------|--------|---------|
| eco  | a    | x    | -2     | 8       |
| reg  | a    | x    | -2     | 8       |
| eco  | a    | x    | -4     | 8       |
| reg  | a    | x    | -4     | 8       |
| eco  | a    | f    | -19    | 8       |
| reg  | a    | f    | -19    | 8       |
| eco  | a    | f    | -24    | 8       |
| reg  | a    | f    | -24    | 8       |
| eco  | b    | g    | -10    | 8       |
| reg  | b    | g    | -10    | 8       |
| eco  | b    | q    | 10     | 8       |
| reg  | b    | q    | 10     | 8       |
| eco  | c    | e    | 29     | 8       |
| reg  | c    | e    | 29     | 8       |
| eco  | f    | y    | 8      | 8       |
| reg  | f    | y    | 8      | 8       |
| eco  | g    | z    | -2     | 8       |
| reg  | g    | z    | -2     | 8       |
| eco  | q    | v    | -3     | 8       |
| reg  | q    | v    | -3     | 8       |
| eco  | e    | a    | 22     | 8       |
| reg  | e    | a    | 22     | 8       |
| eco  | v    | m    | -32    | 8       |
| reg  | v    | m    | -32    | 8       |
| eco  | a    | n    | 4      | 8       |
| reg  | a    | n    | 4      | 8       |
| eco  | a    | k    | 4      | 8       |
| reg  | a    | k    | 4      | 8       |

structure(list(tier = c("eco", "reg", "eco", "reg", "eco", "reg", 
"eco", "reg", "eco", "reg", "eco", "reg", "eco", "reg", "eco", 
"reg", "eco", "reg", "eco", "reg", "eco", "reg", "eco", "reg", 
"eco", "reg", "eco", "reg"), hop1 = c("a", "a", "a", "a", "a", 
"a", "a", "a", "b", "b", "b", "b", "c", "c", "f", "f", "g", "g", 
"q", "q", "e", "e", "v", "v", "a", "a", "a", "a"), hop2 = c("x", 
"x", "x", "x", "f", "f", "f", "f", "g", "g", "q", "q", "e", "e", 
"y", "y", "z", "z", "v", "v", "a", "a", "m", "m", "n", "n", "k", 
"k"), cutoff = c(-2L, -2L, -4L, -4L, -19L, -19L, -24L, -24L, 
-10L, -10L, 10L, 10L, 29L, 29L, 8L, 8L, -2L, -2L, -3L, -3L, 22L, 
22L, -32L, -32L, 4L, 4L, 4L, 4L), landing = c(8L, 8L, 8L, 8L, 
8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 
8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L)), class = "data.frame", row.names = c(NA, 
-28L))

Базовое значение столбца cnt в mydata для каждой строки я хочу динамически выбирать столбец с cnt и cnt-1 в качестве индекса и условно фильтровать их в mydata2 и создавать новый столбец в mydata с максимальным значением, соответствующим отсечке столбца

Я написал a для l oop, но мой набор данных слишком велик, и обработка for l занимает много времени a oop.

Ищу альтернативное решение, которое быстрее с использованием функции apply или dplyr

for (i in 1:nrow(my_data)){
  x <- my_data[i,"cnt"]
  p <- my_data[i,3+x]
  q <- my_data[i,3+x-1]
  r <- my_data[i,3]
  a <- my_data[i,9]

  my_data[i,10] <- my_data2%>%
                  filter(hop1==q,hop2 ==p,tier==r,landing<=a)%>%
                  summarise(max(cutoff))
}

Ниже показан результат l oop

| src | des | tier | hop1 | hop2 | hop3 | hop4 | cnt | arvv | max cutoff |
|-----|-----|------|------|------|------|------|-----|------|------------|
| a   | x   | eco  | a    | x    | NA   | NA   | 2   | 8.49 | -2         |
| a   | x   | reg  | a    | x    | NA   | NA   | 2   | 8.49 | -2         |
| a   | y   | eco  | a    | f    | y    | NA   | 3   | 8.49 | 8          |
| a   | y   | reg  | a    | f    | y    | NA   | 3   | 8.49 | 8          |
| b   | z   | eco  | b    | g    | z    | NA   | 3   | 8.49 | -2         |
| b   | z   | reg  | b    | g    | z    | NA   | 3   | 8.49 | -2         |
| b   | m   | eco  | b    | q    | v    | m    | 4   | 8.49 | -32        |
| b   | m   | reg  | b    | q    | v    | m    | 4   | 8.49 | -32        |
| c   | n   | eco  | c    | e    | a    | n    | 4   | 8.49 | 4          |
| c   | n   | reg  | c    | e    | a    | n    | 4   | 8.49 | 4          |
| c   | k   | eco  | c    | e    | a    | k    | 4   | 8.49 | 4          |
| c   | k   | reg  | c    | e    | a    | k    | 4   | 8.49 | 4          |

1 Ответ

0 голосов
/ 26 июня 2020

Это сработает, но я не знаю, намного ли это быстрее:

my_data$max_cutoff <- unname(unlist(apply(my_data, 1, function(data) {
        x <- as.numeric(data["cnt"])
        p <- data[3 + x]
        q <- data[3 + x - 1]
        r <- data[3]
        a <- data[9]
        
        my_data2 %>%
                filter(hop1 == q, hop2 == p, tier == r, landing <= a) %>%
                summarise(max(cutoff))
})))
> my_data
   src des tier hop1 hop2 hop3 hop4 cnt arvv max_cutoff
1    a   x  eco    a    x <NA> <NA>   2 8.49         -2
2    a   x  reg    a    x <NA> <NA>   2 8.49         -2
3    a   y  eco    a    f    y <NA>   3 8.49          8
4    a   y  reg    a    f    y <NA>   3 8.49          8
5    b   z  eco    b    g    z <NA>   3 8.49         -2
6    b   z  reg    b    g    z <NA>   3 8.49         -2
7    b   m  eco    b    q    v    m   4 8.49        -32
8    b   m  reg    b    q    v    m   4 8.49        -32
9    c   n  eco    c    e    a    n   4 8.49          4
10   c   n  reg    c    e    a    n   4 8.49          4
11   c   k  eco    c    e    a    k   4 8.49          4
12   c   k  reg    c    e    a    k   4 8.49          4

ВАЖНО

Код, который вы указываете с dput() в своем вопросе, по-прежнему не создает «начальный» my_data (несмотря на комментарий @ Daniel), а скорее окончательный желаемый вывод. т.е. это то, что мне нужно было сделать, чтобы получить начальную my_data. Обновите свой вопрос:

my_data <- structure(list(src = c("a", "a", "a", "a", "b", "b", "b", "b", 
    "c", "c", "c", "c"), des = c("x", "x", "y", "y", "z", "z", "m", 
    "m", "n", "n", "k", "k"), tier = c("eco", "reg", "eco", "reg", 
    "eco", "reg", "eco", "reg", "eco", "reg", "eco", "reg"), hop1 = c("a", 
    "a", "a", "a", "b", "b", "b", "b", "c", "c", "c", "c"), hop2 = c("x", 
    "x", "f", "f", "g", "g", "q", "q", "e", "e", "e", "e"), hop3 = c(NA, 
    NA, "y", "y", "z", "z", "v", "v", "a", "a", "a", "a"), hop4 = c(NA, 
    NA, NA, NA, NA, NA, "m", "m", "n", "n", "k", "k"), cnt = c(2L, 
    2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L), arvv = c(8.49, 8.49, 
    8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49, 8.49), 
        `max(cutoff)` = c(-2L, -2L, 8L, 8L, -2L, -2L, -32L, -32L, # why is this already here???
        4L, 4L, 4L, 4L)), row.names = c(NA, -12L), class = "data.frame")

my_data$`max(cutoff)` <- NULL
...