2017-05-26 86 views
0

我有一组变量,其中包含有关人员是否有有史以来有某些健康状况的数据。例如,“你有过心脏病发作吗?”有条件地继续前进和后退

如果他们在观察2时说“是”,那么在观察3和4时答案仍然是。但是,在观察1时不一定是。心脏病发作可能发生在观察1和2之间。

如果他们说“不”,在观察2,那么答案是否定的意见1.但是,它不一定没有在观察3或4

这里是一个重复的例子:

df <- tibble(
    id = rep(1:3, each = 4), 
    obs = rep(1:4, times = 3), 
    mi_ever = c(NA, 0, 1, NA, NA, 0, NA, NA, NA, 1, NA, NA) 
) 
df 
    id obs mi_ever 
1 1 1  NA 
2 1 2  0 
3 1 3  1 
4 1 4  NA 
5 2 1  NA 
6 2 2  0 
7 2 3  NA 
8 2 4  NA 
9 3 1  NA 
10 3 2  1 
11 3 3  NA 
12 3 4  NA 

将我的0(否)向后移动使用zoo :: na.locf携带我的1(是)前进。但是,我不知道如何进行0的向后的。理想情况下,我想下面的结果:

id obs mi_ever mi_ever_2 
1 1 1  NA   0 
2 1 2  0   0 
3 1 3  1   1 
4 1 4  NA   1 
5 2 1  NA   0 
6 2 2  0   0 
7 2 3  NA  NA 
8 2 4  NA  NA 
9 3 1  NA  NA 
10 3 2  1   1 
11 3 3  NA   1 
12 3 4  NA   1 

我已经签出以下职位,但没有人可以覆盖我问这里到底是什么。

Carry last Factor observation forward and backward in group of rows in R

Forward and backward fill data frame in R

making a "dropdown" function in R

任何帮助表示赞赏。

回答

2

基本上我标志着序列中的项目第1后成为1和之前的最后一个0的那些成为0

ever <- function (x) min(which(x == 1)) 
NA_1 <- function(x) seq_along(x) > ever(x) #could have done in one function 
# check to see if working 
ave(df$mi_ever, df$id, FUN= function(x){ x[NA_1(x) ] <- 1; x}) 
[1] NA 0 1 1 NA 0 NA NA NA 1 1 1 

NA_0 <- function(x) seq_along(x) < not_yet(x) 
not_yet <- function(x){ max(which(x==0)) } 
# make temporary version of 1-modified column 
temp1 <- ave(df$mi_ever, df$id, FUN= function(x){ x[NA_1(x) ] <- 1; x}) 
df$ever2 <- ave(temp1, df$id, FUN= function(x){ x[NA_0(x) ] <- 0; x}) 
# then make final version; could have done it "in place" I suppose. 
df 
# A tibble: 12 x 4 
     id obs mi_ever ever2 
    <int> <int> <dbl> <dbl> 
1  1  1  NA  0 
2  1  2  0  0 
3  1  3  1  1 
4  1  4  NA  1 
5  2  1  NA  0 
6  2  2  0  0 
7  2  3  NA NA 
8  2  4  NA NA 
9  3  1  NA NA 
10  3  2  1  1 
11  3  3  NA  1 
12  3  4  NA  1 

如果需要抑制应该是可能的警告。

0

我接受了@ 42-以上的答案(谢谢!),并稍微调整了一下以进一步满足我的需求。具体而言,我:

  • 注意警告“没有非缺少参数min;返回Infno非缺少参数为max;返回-Inf”。
  • 将单独的功能组合成单个功能(尽管单独的功能对学习非常有用)。
  • 添加了一个可选的check_logic参数。当为真时,如果0在1之后,则该函数将返回9。这表示数据错误或逻辑缺陷,需要进一步调查。
  • 增加了一个使用data.table函数和多个变量的例子。这更准确地表示了我在现实生活中如何使用该功能,并且我认为这可能对其他人有用。

功能:

dt <- data.table(
    id = rep(1:3, each = 4), 
    obs = rep(1:4, times = 3), 
    mi_ever = c(NA, 0, 1, NA, NA, 0, NA, NA, NA, 1, NA, NA), 
    diab_ever = c(0, NA, NA, 1, 1, NA, NA, 0, 0, NA, NA, NA) 
) 

遍历多个变量快速使用data.table:

distribute_ever <- function(x, check_logic = TRUE, ...) { 
    if (check_logic) { 
    if (length(which(x == 1)) > 0 & length(which(x == 0)) > 0) { 
     if (min(which(x == 1)) < max(which(x == 0))) { 
     x <- 9        # Set x to 9 if zero comes after 1 
     } 
    } 
    } 
    ones <- which(x == 1)      # Get indices for 1's 
    if (length(ones) > 0) {     # Prevents warning 
    first_1_by_group <- min(which(x == 1)) # Index first 1 by group 
    x[seq_along(x) > first_1_by_group] <- 1 # Set x at subsequent indices to 1 
    } 
    zeros <- which(x == 0)     # Get indices for 0's 
    if (length(zeros) > 0) {     # Prevents warning 
    last_0_by_group <- max(which(x == 0)) # Index last 0 by group 
    x[seq_along(x) < last_0_by_group] <- 0 # Set x at previous indices to 0 
    } 
    x 
} 

新多 “曾经” 变量和某些情况下0之后1重复的例子, (通过组处理):

ever_vars <- c("mi_ever", "diab_ever") 

dt[, paste0(ever_vars, "_2") := lapply(.SD, distribute_ever), 
    .SDcols = ever_vars, 
    by = id][] 

个结果:

id obs mi_ever diab_ever mi_ever_2 diab_ever_2 
1: 1 1  NA   0   0   0 
2: 1 2  0  NA   0   NA 
3: 1 3  1  NA   1   NA 
4: 1 4  NA   1   1   1 
5: 2 1  NA   1   0   9 
6: 2 2  0  NA   0   9 
7: 2 3  NA  NA  NA   9 
8: 2 4  NA   0  NA   9 
9: 3 1  NA   0  NA   0 
10: 3 2  1  NA   1   NA 
11: 3 3  NA  NA   1   NA 
12: 3 4  NA  NA   1   NA 

对于每个输入“曾经”变量,我们有:

  • 创建一个新的变量,“_2”附加到输入变量名的末尾。你也可以编辑“就地”为42指出,但我喜欢能够仔细检查我的数据。
  • 零点向后移动,零点向前移动。
  • 在零之后和之前(id内)的NA不变。
  • 如果在1(是的,我已经...)出现0(不,我从来没有...),就像人2对糖尿病的反应一样,那么函数返回9分的。
  • 如果我们将check_logic设置为FALSE,则1将胜出并替换0的