使用ifelse()识别数据中不一致的响应

时间:2018-10-03 11:45:24

标签: r data-manipulation data-cleaning

我有一个长格式的数据框,用于回答关于青春期状态vb_的重复问题,大约在每年9、10、11、13、14、15、16和17岁时进行。

每年要求参与者将他们的发展从1评估为5,其中1代表最不发达,5代表最发达。

我想使用R的ifelse()来识别不一致的响应,即那些报告的某一阶段的水平低于前几年的响应。

这里有一些20个人的虚假示例数据:

vb <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
                        2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 
                        4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 
                        6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 8L, 
                        8L, 8L, 8L, 8L, 8L, 8L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 
                        10L, 10L, 10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 11L, 
                        11L, 11L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 13L, 13L, 13L, 
                        13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 
                        15L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 16L, 16L, 16L, 16L, 
                        16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 18L, 18L, 
                        18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 19L, 19L, 19L, 19L, 
                        19L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 20L), age = c(9L, 10L, 
                                                                              11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 
                                                                              17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 
                                                                              14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 
                                                                              10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 
                                                                              16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 
                                                                              13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 
                                                                              9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 
                                                                              15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 
                                                                              11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 
                                                                              17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 
                                                                              14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 
                                                                              10L, 11L, 13L, 14L, 15L, 16L, 17L, 9L, 10L, 11L, 13L, 14L, 15L, 
                                                                              16L, 17L), vb_ = c(1L, 1L, 1L, 3L, 4L, 4L, 4L, 5L, 2L, 2L, 3L, 
                                                                                                 4L, 5L, 5L, 5L, 5L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 2L, 1L, 3L, 
                                                                                                 4L, 4L, 5L, 5L, 5L, 2L, 2L, 1L, 3L, 4L, 3L, 4L, 4L, 1L, 1L, 1L, 
                                                                                                 3L, 4L, 4L, 5L, 5L, 1L, 1L, 2L, 4L, 4L, 4L, 5L, 5L, 2L, 2L, 2L, 
                                                                                                 4L, 5L, 4L, 4L, 5L, 2L, 2L, 1L, 4L, 5L, 5L, 5L, 5L, 1L, 2L, 3L, 
                                                                                                 4L, 5L, 5L, 4L, 5L, 1L, 1L, 1L, 4L, 4L, 5L, 5L, 5L, 1L, 1L, 1L, 
                                                                                                 1L, 4L, 4L, 4L, 4L, 1L, 1L, 3L, 4L, 4L, 4L, 5L, 5L, 1L, 1L, 1L, 
                                                                                                 4L, 4L, 5L, 5L, 5L, 2L, 2L, 2L, 2L, 4L, 4L, 5L, 5L, 2L, 3L, 3L, 
                                                                                                 4L, 4L, 5L, 5L, 5L, 1L, 1L, 2L, 2L, 4L, 5L, 5L, 5L, 1L, 1L, 1L, 
                                                                                                 3L, 3L, 4L, 5L, 5L, 1L, 1L, 1L, 2L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 
                                                                                                 2L, 4L, 4L, 4L, 4L)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                           -160L), .Names = c("id", "age", "vb_"))

2 个答案:

答案 0 :(得分:2)

如果您坚持使用ifelse方法,则可以执行以下操作:

vb <- vb[order(vb$id, vb$age), ]
vb$inconsistent <- ifelse(vb$id == lag(vb$id), 
                          ifelse(vb$vb_ < lag(vb$vb_), "inconsistent", ""), 
                          "")
vb$inconsistent[1] <-  ""

    id age vb_ inconsistent
1    1   9   1             
2    1  10   1             
3    1  11   1             
4    1  13   3             
5    1  14   4             
6    1  15   4             
7    1  16   4             
8    1  17   5             
9    2   9   2             
10   2  10   2             
11   2  11   3             
12   2  13   4             
13   2  14   5             
14   2  15   5             
15   2  16   5             
16   2  17   5             
17   3   9   2             
18   3  10   3             
19   3  11   3             
20   3  13   3             
21   3  14   4             
22   3  15   4             
23   3  16   4             
24   3  17   5             
25   4   9   2             
26   4  10   1 inconsistent
27   4  11   3             
...

或者使用dplyr的一种方法是:

library(dplyr)

vb %>% 
  group_by(id) %>% 
  arrange(id, age) %>% 
  mutate(vb_diff = vb_ - lag(vb_)) %>% 
  filter(vb_diff < 0)

# A tibble: 6 x 4
# Groups:   id [5]
     id   age   vb_ vb_diff
  <int> <int> <int>   <int>
1     4    10     1      -1
2     5    11     1      -1
3     5    15     3      -1
4     8    15     4      -1
5     9    11     1      -1
6    10    16     4      -1

答案 1 :(得分:1)

您在这里。

vb <- vb[order(vb$id, vb$age),]

vb$decreasingdevelopment <- c(0, diff(vb$vb_))<0 #difference between this score and previous <0
vb$sameperson <- c(0, diff(vb$id))==0 #is this the same participant than previous

vb$inconsistency <- vb$decreasingdevelopment&vb$sameperson #ifelse(vb$devdiff&vb$sameperson, T, F)
which(vb$inconsistency)
#[1] 26 35 38 62 67 79

请注意,可以使用ifelse(),但不是必须的。

PS:为使答案完整,您应始终使用以下内容:

vb$inconsistency_robust <- apply(vb, 1, function(x) length(which(vb$vb_>x["vb_"]&vb$age<x["age"]&vb$id==x["id"]))>0)
#x["decreasingdevelopment"]&x["sameperson"])
all.equal(which(vb$inconsistency_robust), which(vb$inconsistency))

#> which(vb$inconsistency_robust) 
#[1] 26 35 38 62 63 67 79
#> which(vb$inconsistency)
#[1] 26 35 38 62 67 79

请注意,健壮的方法是如何发现所有不一致的地方的,而我更幼稚的ifelse()方法仅是逐行比较。