R - 长格式循环按id和日递增1

时间:2015-07-11 16:05:57

标签: r loops increment rcpp

我面临一个简单问题。 我的数据包含以下变量:BCSID id DD MM DAY。 个人标识符,id-day标识符,日历日,日历月和星期几。 DD_flag是我需要创建的变量,以便更正错误的DD日期,因为它们不会根据DAY日递增。

我的数据看起来像这样

      BCSID       id DD MM DAY
200 B10011Q B10011Q2 24 10   2
201 B10011Q B10011Q2 24 10   2
202 B10011Q B10011Q2 24 10   2
203 B10011Q B10011Q2 24 10   2
204 B10011Q B10011Q2 24 10   2
205 B10011Q B10011Q2 24 10   2
206 B10011Q B10011Q2 24 10   2
207 B10011Q B10011Q3 24 10   3
208 B10011Q B10011Q3 24 10   3
209 B10011Q B10011Q3 24 10   3
210 B10011Q B10011Q3 24 10   3
211 B10011Q B10011Q3 24 10   3
212 B10011Q B10011Q3 24 10   3
213 B10011Q B10011Q3 24 10   3
214 B10011Q B10011Q3 24 10   3  

我将根据DD_flag

创建我的DD变量
dtadate$DD_flag <- as.numeric(dtadate$DD)

我需要做的是,每当DD_flag每个标识符DAY更改一天时,只需将 +1 增加到BCSID变量。

我认为为我的循环使用折叠的id id可能更简单。

1

我尝试过R循环但是 我不确定为什么这个解决方案是错误的

for(i in 2:nrow(dtadate)){
  if( dtadate$id[i] == dtadate$id[i-1] )
  { dtadate$DD_flag[i] = dtadate$DD_flag[i] + 1 }
}

2

我尝试了一个Rcpp解决方案,它几乎给了我正确的输出。 我在这里使用了BCSIDDAY

增量是正确的,但不幸的是,不会重复使用循环其余部分的增量值。

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]] 
NumericVector TimeAddOneCpp(CharacterVector idDay, CharacterVector Day, NumericVector time) {

  int n = idDay.size();
  int len = n ; 

  for ( int i = 1; i < len; ++i ) {
    if( ( idDay[i] == idDay[i - 1] ) & 
        ( Day[i] != Day [i - 1] )
        )
      time[i] = time[i-1] + 1; 
  }

  return time;
}

功能

TimeAddOneCpp(idDay = dtadate$BCSID, Day = dtadate$DAY, time = dtadate$DD_flag)

预期输出

我想要的输出是以下

      BCSID       id DD MM DAY DD_flag
200 B10011Q B10011Q2 24 10   2      24
201 B10011Q B10011Q2 24 10   2      24
202 B10011Q B10011Q2 24 10   2      24
203 B10011Q B10011Q2 24 10   2      24
204 B10011Q B10011Q2 24 10   2      24
205 B10011Q B10011Q2 24 10   2      24
206 B10011Q B10011Q2 24 10   2      24
207 B10011Q B10011Q3 24 10   3      25
208 B10011Q B10011Q3 24 10   3      25
209 B10011Q B10011Q3 24 10   3      25
210 B10011Q B10011Q3 24 10   3      25
211 B10011Q B10011Q3 24 10   3      25
212 B10011Q B10011Q3 24 10   3      25
213 B10011Q B10011Q3 24 10   3      25
214 B10011Q B10011Q3 24 10   3      25
215 B10011Q B10011Q3 24 10   3      25
216 B10011Q B10011Q3 24 10   3      25
217 B10011Q B10011Q3 24 10   3      25
218 B10011Q B10011Q3 24 10   3      25
219 B10011Q B10011Q3 24 10   3      25
220 B10011Q B10011Q4 24 10   4      26
...

因此,每次DAY更改每个BCSID时,基于DD_flag的{​​{1}}都应增加 +1

数据

DD

3 个答案:

答案 0 :(得分:1)

一种选择是在原始对象之外为DD_flag创建所需的值,然后将它们合并。让我们调用您发布的数据帧z。所以:

flags <- data.frame(id = unique(z$id), DD_flag = seq(length(unique(z$id))))
z2 <- merge(z, flags, all.x = TRUE)

该方法假设您不关心这些标志的顺序。如果这样做,您只需要在第一行中或之前以所需顺序放置id变量的唯一值。

该方法还假设您在合并时尚未在z中具有名为DD_flag的变量。如果这样做,您可以在合并之前运行它:

z$DD_flag <- NULL

答案 1 :(得分:1)

library(dplyr)
dta %>% 
  group_by(BCSID) %>% 
  mutate(DD_flag = c(0, cumsum(diff(as.integer(DAY))))+as.integer(DD))

# Source: local data frame [101 x 6]
# Groups: BCSID
# 
#      BCSID       id DD MM DAY DD_flag
# 1  B10011Q B10011Q2 24 10   2      24
# 2  B10011Q B10011Q2 24 10   2      24
# 3  B10011Q B10011Q2 24 10   2      24
# 4  B10011Q B10011Q2 24 10   2      24
# 5  B10011Q B10011Q2 24 10   2      24
# 6  B10011Q B10011Q2 24 10   2      24
# 7  B10011Q B10011Q2 24 10   2      24
# 8  B10011Q B10011Q3 24 10   3      25
# 9  B10011Q B10011Q3 24 10   3      25
# 10 B10011Q B10011Q3 24 10   3      25
# ..     ...      ... .. .. ...     ...

答案 2 :(得分:1)

这可能是一种可能的解决方案

library(data.table)
setDT(dta)
out = rbindlist(
      lapply(split(dta, dta$BCSID), 
      function(x){ x[, DD_flag := (as.numeric(x$DD) + .GRP)-1, by = DAY]}))

 #> out
 #     BCSID       id DD MM DAY DD_flag
 #1: B10011Q B10011Q2 24 10   2      24
 #2: B10011Q B10011Q2 24 10   2      24
 #3: B10011Q B10011Q2 24 10   2      24
 #4: B10011Q B10011Q2 24 10   2      24
 #5: B10011Q B10011Q2 24 10   2      24
 #6: B10011Q B10011Q2 24 10   2      24
 #7: B10011Q B10011Q2 24 10   2      24
 #8: B10011Q B10011Q3 24 10   3      25
 #9: B10011Q B10011Q3 24 10   3      25
#10: B10011Q B10011Q3 24 10   3      25
#11: B10011Q B10011Q3 24 10   3      25
#12: B10011Q B10011Q3 24 10   3      25
#13: B10011Q B10011Q3 24 10   3      25
#14: B10011Q B10011Q3 24 10   3      25
#15: B10011Q B10011Q3 24 10   3      25
#...