Найдите максимум в группе, подмножество подмножеством из другого фрейма данных, чтобы выбрать другие значения - PullRequest
0 голосов
/ 09 июля 2020

У меня есть два data.frames df1 с необработанными данными. df2 содержит информацию о том, где искать в df1. df1 имеет группы, определяемые идентификатором. В этих группах подмножество определяется параметрами df2 $ value_a1 и df2 $ value_a2, которые представляют диапазон строк для поиска в группе. В этой подгруппе я хочу найти максимальное значение_a, чтобы выбрать значение_b.

код для df1 и df2

df1 <- data.frame("id" = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), "value_a" = c(0, 10, 21, 30, 43, 53, 69, 81, 93, 5, 16, 27, 33, 45, 61, 75, 90, 2, 11, 16, 24, 31, 40, 47, 60, 75, 88), "value_b" = c(100, 101, 100, 95, 90, 104, 88, 84, 75, 110, 105, 106, 104, 95, 109, 96, 89, 104, 104, 104, 103, 106, 103, 101, 99, 98, 97), "value_c" = c(0, -1, -2, -2, -2, -2, -1, -1, 0, 0, 0, 0, 1, 1, 2, 2, 1, -1, 0, 0, 1, 1, 2, 2, 1, 1, 0), "value_d" = c(1:27))
df2 <- data.frame("id" = c(1, 2, 3), "value_a1" = c(21, 33, 16), "value_a2" = c(69, 75, 60))

Это df1

   id value_a value_b value_c value_d
1   1       0     100       0       1
2   1      10     101      -1       2
3   1      21     100      -2       3
4   1      30      95      -2       4
5   1      43      90      -2       5
6   1      53     104      -2       6
7   1      69      88      -1       7
8   1      81      84      -1       8
9   1      93      75       0       9
10  2       5     110       0      10
11  2      16     105       0      11
12  2      27     106       0      12
13  2      33     104       1      13
14  2      45      95       1      14
15  2      61     109       2      15
16  2      75      96       2      16
17  2      90      89       1      17
18  3       2     104      -1      18
19  3      11     104       0      19
20  3      16     104       0      20
21  3      24     103       1      21
22  3      31     106       1      22
23  3      40     103       2      23
24  3      47     101       2      24
25  3      60      99       1      25
26  3      75      98       1      26
27  3      88      97       0      27

Это df2

  id value_a1 value_a2
1  1       21       69
2  2       33       75
3  3       16       60

Мой результат будет df3, который будет выглядеть так

  id value_a value_c
1  1      53      -2
2  2      61       2
3  3      31       1

Я написал этот код, чтобы показать свою линию мышления.

df3 <- df1 %>%
  group_by(id) %>%
  filter(value_a >= df2$value_a1 & value_a <= df2$value_a2) %>%
  filter(value_a == max(value_a)) %>%
  pull(value_b)

Это однако генерирует значение с тремя записями:

[1] 88 95 99

Это не максимальное значение_b ...

Возможно, by() будет работать, но это застревает при использовании функции на двух разных df's.

Такое ощущение, что я почти у цели, но все еще далеко ...

Ответы [ 3 ]

1 голос
/ 09 июля 2020

Почему бы вам не попробовать слияние? Затем с синтаксисом data.table:

library(data.table)
df3 <- merge(df1, df2, by = "id", all.x = TRUE)

max_values <- df3[value_a > value_a1 & value_a < value_a2, max(value_b), by = "id"]

max_values
# id  V1
# 1:  1 104
# 2:  2 109
# 3:  3 106
1 голос
/ 09 июля 2020

Я бы сделал это с помощью пакета data.table, поскольку это именно то, к чему я привык.

library(data.table)

dt.1 <- data.table("id" = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), "value_a" = c(0, 10, 21, 30, 43, 53, 69, 81, 93, 5, 16, 27, 33, 45, 61, 75, 90, 2, 11, 16, 24, 31, 40, 47, 60, 75, 88), "value_b" = c(100, 101, 100, 95, 90, 104, 88, 84, 75, 110, 105, 106, 104, 95, 109, 96, 89, 104, 104, 104, 103, 106, 103, 101, 99, 98, 97), "value_c" = c(0, -1, -2, -2, -2, -2, -1, -1, 0, 0, 0, 0, 1, 1, 2, 2, 1, -1, 0, 0, 1, 1, 2, 2, 1, 1, 0), "value_d" = c(1:27))
dt.2 <- data.table("id" = c(1, 2, 3), "value_a1" = c(21, 33, 16), "value_a2" = c(69, 75, 60))

dt.3 <- dt.1[id %in% dt.2[,id],max(value_b), by="id"]
setnames(dt.3, "V1", "max_value_b")
dt.3

Чтобы получить соответствующую строку, где b - максимальные значения, есть несколько способов, вот тот, где я только измененная строка из предыдущего кода

dt.1[id %in% dt.2[,id],.SD[which.max(value_b), .(value_a, value_b, value_c, value_d)], by="id"]

.SD означает подтаблицу, которую вы уже выбрали с помощью by, поэтому для каждого идентификатора выбирается локальный max b, а затем возвращается таблица which.max() выбирает row и, наконец, .() - это псевдоним для списка, поэтому перечисляются столбцы, которые вы sh из этой таблицы.

Возможно, более удобочитаемым подходом будет сначала выбрать нужные строки

max.b.rows <- dt.1[id %in% dt.2[,id], which.max(value_b), by="id"][,V1]
dt.3 <- dt.1[max.b.rows,]

Кстати, часть id %in% dt.2[,id] предназначена только для того, чтобы убедиться, что вы выбираете максимумы только для тех идентификаторов в таблице 2

Best

1 голос
/ 09 июля 2020

Вы можете попробовать это. Надеюсь, это поможет.

df1 %>% left_join(df2) %>% mutate(val=ifelse(value_a>value_a1 & value_a<value_a2,value_b,NA)) %>%
  group_by(id) %>% summarise(val=max(val,na.rm=T))

# A tibble: 3 x 2
     id   val
  <dbl> <dbl>
1     1   104
2     2   109
3     3   106
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...