R: новый столбец разницы строк от максимального значения другого столбца в соответствии с группой - PullRequest
0 голосов
/ 10 сентября 2018

Название вопроса может быть неясным, но я надеюсь, что эти коды четко продемонстрируют мою проблему.

У меня есть фрейм данных с тремя столбцами. датчик $ (A и B); $ час дня (0-4); и значение $, взятое температурой (1-5).

 new.df <- data.frame(
 sensor = c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B"), 
 hour_day = c(0:4, 0:4),
 value = c(1, 1, 3, 1, 2, 1, 3, 4, 5, 2)

new.df

   sensor hour_day value
1       A        0     1
2       A        1     1
3       A        2     3
4       A        3     1
5       A        4     2
6       B        0     1
7       B        1     3
8       B        2     4
9       B        3     5
10      B        4     2

Я хочу создать новый столбец, который показывает разницу в часе от часа с максимальным значением в соответствии с сенсором .

Желаемый результат

   sensor value hour_day hour_from_max_hour
1       A     1        0                 -2
2       A     1        1                 -1
3       A     3        2                  0
4       A     1        3                  1
5       A     2        4                  2
6       B     1        0                 -3
7       B     3        1                 -2
8       B     4        2                 -1
9       B     5        3                  0
10      B     2        4                  1

Обратите внимание, что для датчика A (макс. = Час 2) и датчика B (макс. = Час 3). Мне просто нужен новый столбец, в котором указано, на сколько часов отличается группа значений датчика от максимального значения датчика.

Заранее спасибо и, пожалуйста, дайте мне знать, если смогу предоставить больше информации.

EDIT Предыдущий ответ был очень полезным, я забыл, что в этой задаче есть еще одна переменная (день). Кроме того, иногда в столбце присутствует более одного максимума. В таком случае я хотел бы основывать разницу на максимуме first .

df_add <- data.frame(
  sensor = c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B",
               "A", "A", "A", "A", "A", "B", "B", "B", "B", "B"), 
    hour_day = c(0:4, 0:4, 0:4, 0:4),
    value = c(1, 1, 3, 3, 2,
              3, 2, 4, 4, 1,
              1, 5, 6, 6, 2,
              2, 1, 3, 3, 1),
    day =   c(1, 1, 1, 1, 1, 
              1, 1, 1, 1, 1,
              2, 2, 2, 2, 2,
              2, 2, 2, 2, 2)

)

df_add

   sensor hour_day value day
1       A        0     1   1
2       A        1     1   1
3       A        2     3   1
4       A        3     3   1
5       A        4     2   1
6       B        0     3   1
7       B        1     2   1
8       B        2     4   1
9       B        3     4   1
10      B        4     1   1
11      A        0     1   2
12      A        1     5   2
13      A        2     6   2
14      A        3     6   2
15      A        4     2   2
16      B        0     2   2
17      B        1     1   2
18      B        2     3   2
19      B        3     3   2
20      B        4     1   2

Спасибо за тех, кто внес свой вклад ранее!

Ответы [ 3 ]

0 голосов
/ 10 сентября 2018

Вероятно, я бы так и сделал:

library(plyr)
dd = ddply(new.df, .(sensor), summarize, 
           max.value = max(value),
           hour.of.max = hour_day[which.max(value)])
new.df = merge(new.df, dd, all.x=T, by='sensor')
new.df$hour_from_max_hour = new.df$hour_day - new.df$hour.of.max

Дала вам пару дополнительных столбцов, но вы можете удалить их:

   sensor hour_day value max.value hour.of.max hour_from_max_hour
1       A        0     1         3           2                 -2
2       A        1     1         3           2                 -1
3       A        2     3         3           2                  0
4       A        3     1         3           2                  1
5       A        4     2         3           2                  2
6       B        0     1         5           3                 -3
7       B        1     3         5           3                 -2
8       B        2     4         5           3                 -1
9       B        3     5         5           3                  0
10      B        4     2         5           3                  1
0 голосов
/ 10 сентября 2018

Простая труба может это сделать. Все, что вам нужно сделать, это получить max(value) в инструкции mutate.

new.df %>%
    group_by(sensor) %>%
    mutate(hour_from_max_hour = hour_day - hour_day[which(value == max(value))[1]])
## A tibble: 10 x 4
## Groups:   sensor [2]
#   sensor hour_day value hour_from_max_hour
#   <fct>     <int> <dbl>              <int>
# 1 A             0    1.                 -2
# 2 A             1    1.                 -1
# 3 A             2    3.                  0
# 4 A             3    1.                  1
# 5 A             4    2.                  2
# 6 B             0    1.                 -3
# 7 B             1    3.                 -2
# 8 B             2    4.                 -1
# 9 B             3    5.                  0
#10 B             4    2.                  1
0 голосов
/ 10 сентября 2018
library(dplyr)

new.df.2 <- 
  # First get the hours with the max values
  new.df %>%
  group_by(sensor) %>%
  filter(value == max(value)) %>%
  ungroup() %>%
  select(sensor, max_hour = hour_day) %>%   # This renames hour_day as max_hour
  # Now join that to the original table and make the calculation
  right_join(new.df) %>%
  mutate(hour_from_max_hour = hour_day - max_hour)

Результат:

new.df.2
# A tibble: 10 x 5
   sensor max_hour hour_day value hour_from_max_hour
   <fct>     <int>    <int> <dbl>              <int>
 1 A             2        0     1                 -2
 2 A             2        1     1                 -1
 3 A             2        2     3                  0
 4 A             2        3     1                  1
 5 A             2        4     2                  2
 6 B             3        0     1                 -3
 7 B             3        1     3                 -2
 8 B             3        2     4                 -1
 9 B             3        3     5                  0
10 B             3        4     2                  1
...