检查连续日期并排除奇数条目

时间:2017-10-09 13:05:06

标签: r

编辑!见下文:

我正在尝试使用dplyr创建一个for循环,我似乎错过了一些东西。 我正在尝试做的简化版本在下面的代码中表示。

> df
                    user_id                         var x
1                   1                               a
2                   1                               b
3                   1                               c
4                   2                               d
5                   2                               e
6                   2                               f

我正在尝试过滤掉用户编号1的数据,然后为我的进一步分析创建一个for循环。

df %>%
    filter(user_id==1)%>%
    for(i in 1:nrow()) {
        print(i)
        }

但是,我不断收到相同的消息:

Error in function_list[[k]](value) : object 'i' not found

我希望nrow()函数只将我转换后的df作为变量传递,但显然情况并非如此。我也试过在nrow()中传递df并看看它是如何反应的,但我得到了同样的信息。 我仍然是R初学者,所以我可能错过了一些简单的东西。任何帮助将非常感激!谢谢!

EDITED : 由于简化问题似乎使其更加混乱,我将只列出我的问题。 所以,我已经在一部分用户中报告了月经日,我想清理我的数据。

> df

    user_id    menstruation_date"
1     1          20160602
2     1          20160603
3     1          20160604
4     1          20160605
5     1          20160606
6     1          20160712
7     1          20160909
8     1          20160910
9     1          20160911
10    1          20160912
11    1          20160913
12    6          20160121
13    6          20160122
14    6          20160123
15    6          20160221

让我们考虑用户1.从2016年6月2日到2016年6月6日,用户1报告有她的期间。我想在一个周期内对此进行分组。 但是看看第6行,她只在7月报告了一天。由于月经不太可能持续一天,我想从我的分析中排除这个条目而不考虑这个周期。 我试图通过创建一个检查连续几天的for循环来解决这个问题,并且只考虑至少连续3个月经日存在的周期。

对于我上面粘贴的样本,用户1的所需输出为:

> df

    user_id    menstruation_date"
1     1          20160602
2     1          20160603
3     1          20160604
4     1          20160605
5     1          20160606
6     1          20160909
7     1          20160910
8     1          20160911
9     1          20160912
10    1          20160913

第6行(如上所述)的奇数条目已被删除。

我最终希望为每个用户都这样做。

我希望这篇较长的文字能让问题更加清晰。谢谢!

3 个答案:

答案 0 :(得分:2)

使用dplyr过滤器的想法是消除for循环。 所以,要得到你想要的东西:

df %>% filter(user_id==1)


 user_id var_x
1       1     a
2       1     b
3       1     c

答案 1 :(得分:2)

我已将来自mutate的{​​{1}}组合在一起。但有人可以为此写出更好的解决方案!

dplyr

答案 2 :(得分:0)

使用@amrrs的回答后,我扩展了数据清理。 “月经”是我的数据集(替代上述解决方案中的df),“beginn_local_date”是报告期间的日期。这是代码:

#Cleaning data: exclude female users with non-reliable information
    ##formating dates
menstruation$begin_local_date <- lubridate::ymd(menstruation$begin_local_date)

    ##Each cycle has to have at least 3 days
        ###Stackoverflow solution: thank you amrrs!
new_mens <- menstruation %>% 
    group_by(user_id) %>% 
    mutate(days = begin_local_date - lag(begin_local_date, default = NA)) %>%  
    mutate(days = ifelse(is.na(days),0,days)) %>%
    mutate(flag = ifelse(days + lead(days, default = 0) > days + 1, 1, 0)) %>%
    filter(ifelse(flag + lag(flag, default = TRUE) == 2, FALSE, TRUE)) %>%
    filter(days<2 | days>=21)%>% #if 2 included, then one forgotten day in otherwise full cycle won't be forgotten
    mutate(daysagain=ifelse(days<2,days,0)) %>%
    mutate(group=0)

    #mutate(day.idx2=ifelse(is.na(day.idx),(lag(day.idx2,default=0)+1),1))
count<-0

for (i in 1:length(new_mens$daysagain)) {
    if (new_mens$daysagain[i]==0) {
        count <- count+1
        new_mens$group[i] <- count
    } else {
        new_mens$group[i] <- count
    }
}

new_mens<-new_mens %>%
    group_by(user_id,group) %>%
    mutate(total.per.group=n()) %>%
    filter(total.per.group>=3) %>%
    mutate(helper=1) %>%
    mutate(our.idx=cumsum(helper)) %>%
    ungroup() %>%
    group_by(user_id) %>%
    mutate(total.per.user = n()) %>% 
    filter(total.per.user>=9) %>%
    select(user_id, begin_local_date, days, our.idx)%>%
    ungroup()

结果是一个更干净的数据集,每个循环中的每一天都被编入索引:

> new_mens
   user_id begin_local_date  days our.idx
     <int>           <date> <dbl>   <dbl>
 1       1       2016-06-02     0       1
 2       1       2016-06-03     1       2
 3       1       2016-06-04     1       3
 4       1       2016-06-05     1       4
 5       1       2016-06-06     1       5
 6       1       2016-09-09    59       1
 7       1       2016-09-10     1       2
 8       1       2016-09-11     1       3
 9       1       2016-09-12     1       4
10       1       2016-09-13     1       5