Преобразование фиктивной переменной с наблюдением до и после

У меня есть набор данных панели титульного дня (df1). Для каждого заголовка и заданного дня кодируется объем (том). Есть переменная, которую вы можете рассматривать как лечение (v1). В этом наборе данных всегда есть лечение, но день начала лечения зависит от названия. Когда лечение начинается, оно продолжается до конца периода.

title <- rep(c("x", "y", "z"), each = 5)
day <- rep(c(0,1,2,3,4), times = 3)
volume <- c(0,0,1,1,2,3,0,0,0,0,3,3,4,2,1)
v1 <- c(0,0,1,1,1,0,1,1,1,1,0,0,0,1,1)
df1 <- data.frame(title,day,volume,v1)

Я пытаюсь изменить фиктивную переменную, которая указывает, получил ли заголовок какой-либо объем (отличный от нуля) до И после обработки. Где 1 кодируется в ситуациях, когда заголовок приобрел громкость до и после начала лечения. 0 кодируется, когда заголовок не имеет объема до или после начала обработки. Фрейм данных должен выглядеть так:

title <- rep(c("x", "y", "z"), each = 5)
day <- rep(c(0,1,2,3,4), times = 3)
volume <- c(0,0,1,1,2,3,0,0,0,0,3,3,4,2,1)
v1 <- c(0,0,1,1,1,0,1,1,1,1,0,0,0,1,1)
new_v <- c(0,0,0,0,0,0,0,0,0,0,1,1,1,1,1)
output <- data.frame(title,day,volume,v1,new_v)

Надеюсь, вы, ребята, можете мне помочь.


person Analyticdon    schedule 25.05.2020    source источник
comment
Если я правильно понял вопрос, это потому, что объем во все дни лечения равен 0 для y   -  person Dominik S. Meier    schedule 25.05.2020
comment
Собственно Доминик. Это 0, потому что объем должен быть до и после лечения. У Y есть только объем до лечения, но нет после него.   -  person Analyticdon    schedule 25.05.2020


Ответы (3)


Вот подход с использованием dplyr:

library(dplyr)

df1 %>% 
  group_by(title, v1) %>% 
  mutate(summe = sum(volume)) %>% 
  group_by(title) %>% 
  mutate(dummy_volume = all(summe > 0)) %>% 
  select(-summe)

# A tibble: 15 x 5
# Groups:   title [3]
   title   day volume    v1 dummy_volume
   <fct> <dbl>  <dbl> <dbl> <lgl>       
 1 x         0      0     0 FALSE       
 2 x         1      0     0 FALSE       
 3 x         2      1     1 FALSE       
 4 x         3      1     1 FALSE       
 5 x         4      2     1 FALSE       
 6 y         0      3     0 FALSE       
 7 y         1      0     1 FALSE       
 8 y         2      0     1 FALSE       
 9 y         3      0     1 FALSE       
10 y         4      0     1 FALSE       
11 z         0      3     0 TRUE        
12 z         1      3     0 TRUE        
13 z         2      4     0 TRUE        
14 z         3      2     1 TRUE        
15 z         4      1     1 TRUE 

С Dummy, закодированным как 0/1, как в желаемом выходе:

df1 %>% 
  group_by(title, v1) %>% 
  mutate(summe = sum(volume)) %>% 
  group_by(title) %>% 
  mutate(dummy_volume = as.integer(all(summe > 0))) %>% 
  select(-summe)

# A tibble: 15 x 5
# Groups:   title [3]
   title   day volume    v1 dummy_volume
   <fct> <dbl>  <dbl> <dbl>        <int>
 1 x         0      0     0            0
 2 x         1      0     0            0
 3 x         2      1     1            0
 4 x         3      1     1            0
 5 x         4      2     1            0
 6 y         0      3     0            0
 7 y         1      0     1            0
 8 y         2      0     1            0
 9 y         3      0     1            0
10 y         4      0     1            0
11 z         0      3     0            1
12 z         1      3     0            1
13 z         2      4     0            1
14 z         3      2     1            1
15 z         4      1     1            1
person Dominik S. Meier    schedule 25.05.2020
comment
Я выбрал этот ответ из-за его простоты. - person Analyticdon; 25.05.2020

Вы можете использовать ave и обрабатывать регистр с помощью if/else, когда все обработанные volumes равны нулю.

output <- transform(df1, new_v=ave(volume, title, FUN=function(x) {
  rr <- sum(x[v1 %in% 0], na.rm=T) > 0
  if (sum(x[v1 %in% 1], na.rm=T) == 0) 0
  else rr
}))
#    title day volume v1 new_v
# 1      x   0      0  0     0
# 2      x   1      0  0     0
# 3      x   2      1  1     0
# 4      x   3      1  1     0
# 5      x   4      2  1     0
# 6      y   0      3  0     0
# 7      y   1      0  1     0
# 8      y   2      0  1     0
# 9      y   3      0  1     0
# 10     y   4      0  1     0
# 11     z   0      3  0     1
# 12     z   1      3  0     1
# 13     z   2      4  0     1
# 14     z   3      2  1     1
# 15     z   4      1  1     1

Или если вам нужен dplyr.

library(dplyr)
output <- df1 %>% 
  mutate(new_v=ave(volume, title, FUN=function(x) {
  rr <- sum(x[v1 %in% 0], na.rm=T) > 0
  if (sum(x[v1 %in% 1], na.rm=T) == 0) 0
  else rr
}))
person jay.sf    schedule 25.05.2020

Для каждого title мы можем проверить, есть ли any volume > 0 до лечения (v1 == 0) и после лечения (v1 == 1).

Это можно сделать с помощью dplyr:

library(dplyr)
df1 %>%
  group_by(title) %>%
  mutate(new_v = +(any(volume[v1 == 1] > 0) && any(volume[v1 == 0] > 0)))

#  title   day volume    v1 new_v
#   <chr> <dbl>  <dbl> <dbl> <int>
# 1 x         0      0     0     0
# 2 x         1      0     0     0
# 3 x         2      1     1     0
# 4 x         3      1     1     0
# 5 x         4      2     1     0
# 6 y         0      3     0     0
# 7 y         1      0     1     0
# 8 y         2      0     1     0
# 9 y         3      0     1     0
#10 y         4      0     1     0
#11 z         0      3     0     1
#12 z         1      3     0     1
#13 z         2      4     0     1
#14 z         3      2     1     1
#15 z         4      1     1     1

Или та же логика в data.table:

library(data.table)
setDT(df1)[, new_v := +(any(volume[v1 == 1] > 0) && 
                        any(volume[v1 == 0] > 0)), title]
person Ronak Shah    schedule 25.05.2020