Сопоставление положительных и отрицательных чисел в одной группе — R

#r #dataframe #dplyr

#r #фрейм данных #dplyr

Вопрос:

Я хотел бы сделать следующее:

 id calendar_week value
1    1              10
2    2              2
3    2             -2
4    2              3
5    3              10 
6    3             -10
  

Вывод, который я хочу, — это список идентификаторов (или строк), которые имеют положительное и отрицательное совпадение для данной calendar_week -> что означает, что я хочу, например, идентификаторы 2 и 3, потому что в календарной неделе 2 есть совпадение от -2 до 2. Мне не нужен идентификатор 4, потому что в календарной неделе 2 нет значения -3 и так далее.

вывод:

 id calendar_week value 
2    2              2
3    2             -2
5    3              10 
6    3             -10
  

Комментарии:

1. Как вы получаете 10 и -10 в конечном выводе?

2. Уникальны ли значения в пределах календарной недели?

3. та же календарная неделя и совпадение 10 с отрицательным значением 10

4. может ли он иметь 2 одинаковых значения? 2, 2 и т.д.? каким будет ваш вывод в этом случае? Вы хотите выделить эти строки?

5. Но идентификаторы разные? Что тогда означает «та же группа»?

Ответ №1:

Также можно было бы сделать:

 library(dplyr)

df %>%
  group_by(calendar_week, ab = abs(value)) %>%
  filter(n() > 1) %>% ungroup() %>%
  select(-ab)
  

Вывод:

 # A tibble: 4 x 3
     id calendar_week value
  <int>         <int> <int>
1     2             2     2
2     3             2    -2
3     5             3    10
4     6             3   -10
  

Учитывая ваши дополнительные разъяснения, вы могли бы сделать:

 df %>%
  group_by(calendar_week, value) %>%
  mutate(idx = row_number()) %>%
  group_by(calendar_week, idx, ab = abs(value)) %>%
  filter(n() > 1) %>% ungroup() %>%
  select(-idx, -ab)
  

В измененном фрейме данных:

   id calendar_week value
1  1             1    10
2  2             2     2
3  3             2    -2
4  3             2     2
5  4             2     3
6  5             3    10
7  6             3   -10
8  7             4    10
9  8             4    10
  

Это дает:

 # A tibble: 4 x 3
     id calendar_week value
  <int>         <int> <int>
1     2             2     2
2     3             2    -2
3     5             3    10
4     6             3   -10
  

Комментарии:

1. это хорошо! как бы вы настроили его, чтобы в нем были все совпадения? например, если на той же неделе у нас будет больше совпадений от 2 до -2?

2. Это привело бы к выводу всех совпадений по умолчанию. Если бы у вас было, например, 2, -2, 2, -2 , это просто вывело бы их все. Это также привело бы к выводу, если бы у вас было 2, -2, 2 — если вы не хотите выводить эту последнюю строку, вам потребуется дополнительная конфигурация, но это не было указано в вопросе.

3. это правда! Я не хочу последнего. Вам известны дополнительные конфигурации?

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

5. @Хенрик Борзимовский, конечно, смотри мою правку. @ H 1 решение соответствует примеру, авторы сообщений должны позаботиться о достаточной сложности, но я скорректировал свой ответ

Ответ №2:

Используя tidyverse :

 library(tidyverse)

df %>%
  group_by(calendar_week) %>%
  nest() %>%
  mutate(values = map_chr(data, ~ str_c(.x$value, collapse = ', '))) %>%
  unnest() %>%
  filter(str_detect(values, as.character(-value))) %>%
  select(-values)
  

Вывод :

 calendar_week    id value
          <dbl> <int> <dbl>
1             2     2     2
2             2     3    -2
3             3     5    10
4             3     6   -10
  

Ответ №3:

Если, как указано в комментариях, требуется только одно совпадение, вы могли бы попробовать:

 library(dplyr)

df %>%
  group_by(calendar_week, nvalue = abs(value)) %>% 
  filter(!duplicated(value)) %>%
  filter(sum(value) == 0) %>% 
  ungroup() %>%
  select(-nvalue)

     id calendar_week value
  <int>         <int> <int>
1     2             2     2
2     3             2    -2
3     5             3   -10
4     6             3    10