R: создать новый столбец на основе групп и условий - PullRequest
1 голос
/ 26 февраля 2020

У меня есть фрейм данных с 4 столбцами (часть его показана ниже).

В первом столбце показаны группы, упорядоченные по номерам: 1, 2, ....

Я хочу создать новый столбец "value4". Для каждой группы, если размер группы больше 2 (> = 3), а все значения в столбце «value1» больше 2 (> 2) или меньше -2 (<-2), то медиана соответствующие значения в столбце «значение3» рассчитываются и помещаются в столбец «значение4» для каждой строки этой группы. В противном случае значения из «value2» переносятся в столбец «value4». </p>

g   value1   value2  value3
1     1.1      8       1
1     1.2      8       1
1     1.3      9       1
2     3        10      5
2     4        11      5
2     5        0       4
2     6        1       6
3     -3       2       5
3     -4       3       10
3     -5       4       0
4     -3       1       0
4     -4       1       0

Вывод будет:

g   value1   value2  value3  value4
1     1.1      8       1       8  # for group "1", all the values in "value1" are <2, so the values from column "value2" are taken
1     1.2      8       1       8
1     1.3      9       1       9
2     3        10      5       5  # for group "2", all the values in "value1" are >2, median of numbers 5,5,4,6 from column "value3" is calculated  
2     4        11      5       5
2     5        0       4       5
2     6        1       6       5
3     -3       2       5       5  # for group "3", all the values in "value1" are < -2, median of numbers 5,10,0 from column "value3" is calculated      
3     -4       3       10      5
3     -5       4       0       5
4     -3       1       0       1  # group size less than 3, so the values from column "value2" are taken
4     -4       1       0       1

Я думаю, что могу использовать aggregate (), но я не знаю, как интегрировать условия. Я ценю ваше время и помощь.

Ответы [ 3 ]

0 голосов
/ 26 февраля 2020

Вы можете использовать пакет data.table следующим образом:

library(data.table)
setDT(df)[, value4 := if(.N > 2 & (all(value1 > 2) | all(value1 < -2))) median(value3) else value2, g]
0 голосов
/ 26 февраля 2020

Это идеальная ситуация для case_when () . *

. Вы хотите, чтобы value4 рассчитывалось на основе следующего условия:

Если размер группы > 2 и абсолютное значение всех value1 в группе> 2 => принять медиану value3. В противном случае используйте value2

library(dplyr)
df %>%
  group_by(g) %>%
  mutate(value4 = case_when( (n() > 2) & (all(abs(value1) > 2)) ~ median(value3), 
                            T ~ value2)

* Можно было бы подумать, что мы могли бы использовать здесь if_else(), потому что есть только одно условие, но по какой-то причине оно было неудачным при использовании all() в условии. Я думаю, что это возвращало несколько значений? Неясно, но, может быть, кто-то еще мог бы объяснить.

0 голосов
/ 26 февраля 2020

Исходя из условия, мы можем использовать условие if/else с использованием размера группы (n()), и если all значение1 меньше -2 или больше 2, то получить median значения «значение3» или else вернуть 'значение2'

library(dplyr)
df1 %>%       
   group_by(g) %>%
   mutate(value4 = if(n() > 2 & (all(value1 > 2)| all(value1 < -2))) median(value3) 
       else value2)
# A tibble: 12 x 5
# Groups:   g [4]
#       g value1 value2 value3 value4
#   <int>  <dbl>  <int>  <int>  <dbl>
# 1     1    1.1      8      1      8
# 2     1    1.2      8      1      8
# 3     1    1.3      9      1      9
# 4     2    3       10      5      5
# 5     2    4       11      5      5
# 6     2    5        0      4      5
# 7     2    6        1      6      5
# 8     3   -3        2      5      5
# 9     3   -4        3     10      5
#10     3   -5        4      0      5
#11     4   -3        1      0      1
#12     4   -4        1      0      1

данные

df1 <- structure(list(g = c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 
4L, 4L), value1 = c(1.1, 1.2, 1.3, 3, 4, 5, 6, -3, -4, -5, -3, 
-4), value2 = c(8L, 8L, 9L, 10L, 11L, 0L, 1L, 2L, 3L, 4L, 1L, 
1L), value3 = c(1L, 1L, 1L, 5L, 5L, 4L, 6L, 5L, 10L, 0L, 0L, 
0L)), class = "data.frame", row.names = c(NA, -12L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...