Как создать индексную переменную для уникальных значений X в группе Y? - PullRequest
1 голос
/ 29 мая 2020

У меня есть следующая таблица:

id_question  id_event   num_events
2015012713    49508          1
2015012711    49708          1
2015011523    41808          3
2015011523    44008          3
2015011523    44108          3
2015011522    41508          3
2015011522    43608          3
2015011522    43708          3
2015011521    39708          1
2015011519    44208          1

В третьем столбце указано количество событий по вопросам. Я хочу создать переменную, которая будет индексировать события по вопросам, только если для каждого вопроса есть несколько событий. Это будет выглядеть примерно так:

id_question  id_event   num_events  index_event
2015012713    49508          1          
2015012711    49708          1          
2015011523    41808          3          1
2015011523    44008          3          2
2015011523    44108          3          3
2015011522    41508          3          1
2015011522    43608          3          2
2015011522    43708          3          3
2015011521    39708          1          
2015011519    44208          1          

Как я могу это сделать?

Ответы [ 2 ]

2 голосов
/ 29 мая 2020

Мы можем использовать tidyverse для создания 'index_event' после группировки по 'id_question'. Если количество строк больше 1 (n() >1), тогда получите последовательность строк (row_number()), а параметр по умолчанию в case_when равен NA

library(dplyr)
df1 %>%
   group_by(id_question) %>%
   mutate(index_event = case_when(n() >1 ~ row_number()))
# A tibble: 10 x 4
# Groups:   id_question [6]
#   id_question id_event num_events index_event
#         <int>    <int>      <int>       <int>
# 1  2015012713    49508          1          NA
# 2  2015012711    49708          1          NA
# 3  2015011523    41808          3           1
# 4  2015011523    44008          3           2
# 5  2015011523    44108          3           3
# 6  2015011522    41508          3           1
# 7  2015011522    43608          3           2
# 8  2015011522    43708          3           3
# 9  2015011521    39708          1          NA
#10  2015011519    44208          1          NA

Или с data.table, мы используем rowid в 'id_question' и меняем элементы, которые равны 1 в 'num_events', на NA с NA^ (используя NA^0, NA^1)

library(data.table)
setDT(df1)[, index_event := rowid(id_question) * NA^(num_events == 1)]

Или используя base R, другой вариант с частотой sequence от 'id_question' и измените элементы на NA, как в предыдущем случае

df1$index_event <-  with(df1, sequence(table(id_question)) * NA^(num_events == 1))
df1$index_event
#[1] NA NA  1  2  3  1  2  3 NA NA

data

df1 <- structure(list(id_question = c(2015012713L, 2015012711L, 2015011523L, 
2015011523L, 2015011523L, 2015011522L, 2015011522L, 2015011522L, 
2015011521L, 2015011519L), id_event = c(49508L, 49708L, 41808L, 
44008L, 44108L, 41508L, 43608L, 43708L, 39708L, 44208L), num_events = c(1L, 
1L, 3L, 3L, 3L, 3L, 3L, 3L, 1L, 1L)), class = "data.frame", row.names = c(NA, 
-10L))
1 голос
/ 29 мая 2020

Если num_events = 1, вы можете вернуть NA или создать индекс строки для каждого id_question.

Это можно сделать в базе R:

df$index_event <- with(df, ave(num_events == 1, id_question, 
                       FUN = function(x) replace(seq_along(x), x, NA))) 

df
#   id_question id_event num_events index_event
#1   2015012713    49508          1          NA
#2   2015012711    49708          1          NA
#3   2015011523    41808          3           1
#4   2015011523    44008          3           2
#5   2015011523    44108          3           3
#6   2015011522    41508          3           1
#7   2015011522    43608          3           2
#8   2015011522    43708          3           3
#9   2015011521    39708          1          NA
#10  2015011519    44208          1          NA

dplyr:

library(dplyr)
df %>% 
   group_by(id_question) %>% 
   mutate(index_event = if_else(num_events == 1, NA_integer_, row_number()))

Или data.table:

library(data.table)
setDT(df)
df[,index_event := ifelse(num_events == 1, NA_integer_, seq_len(.N)), id_question]

данные

df <- structure(list(id_question = c(2015012713L, 2015012711L, 2015011523L, 
2015011523L, 2015011523L, 2015011522L, 2015011522L, 2015011522L, 
2015011521L, 2015011519L), id_event = c(49508L, 49708L, 41808L, 
44008L, 44108L, 41508L, 43608L, 43708L, 39708L, 44208L), num_events = c(1L, 
1L, 3L, 3L, 3L, 3L, 3L, 3L, 1L, 1L)),class = "data.frame",row.names = c(NA, -10L))
...