R:循环时间过长

时间:2017-01-19 15:59:35

标签: r loops for-loop dataframe duplicates

问题

我有一个包含3个变量的数据集:一个ID变量,一个TIME变量和一个数值变量X,只有当它与零不同时才会显示在数据集中,如下表所示。

    time  ID  X
238 2007  A   28
239 2008  A   80
240 2014  A   178
241 2012  B   88
242 2011  C   369
243 2003  D   28
244 2004  D   80

我希望在一个独特的数据框中为每个ID设置一个lign,并且每年在2001年到2016年之间,当需要时X = 0。所以这将是一个表,如下所示:

   time  ID  X
1  2001  A   0
2  2002  A   0

7  2007  A   28
8  2008  A   80

14 2014  A   178
17 2001  B   0
7  2012  B   88

我在R文档或此论坛中找不到任何方法

我的工作方式

为了解决这个问题,我有了三个步骤的想法:

1)每个ID号码只保留一行,无论它是哪一年

data2 = data%>%group_by(ID,X)%>%distinct(.keep_all = T)

这导致下表:

    time  ID  X
238 2007  A   28
241 2012  B   88
242 2011  C   369
243 2003  D   28

2)然后我复制每一行以进行每年的观察

timebis = seq(from = 2001, to = 2016, by = 1)
dupl.data2 = data2[rep(1:nrow(data1), each=length(timebis)), ]
dupl.data1$X = 0

我现在每个ID都有16个观察结果。

3)使用双循环

填充dupl.data1 $ X列
i=1
j=1 
for(i in 1:length(dupl.data2$ID)){
  for(j in 1:length(data$ID)){
    if (dupl.data2$timebis[i]==data$time[j] & dupl.data2$ID[i]==data$ID[j]) 
       {dupl.data2$X[i]=data$X[j]} 
  j=j+1  
}
  j=1 
  i=i+1
}

结论

它适用于小的子样本,但我的原始数据库有大约30万个观测值,带零的数据集要大得多。 我需要提高我的代码效率或想法来解决这个问题。

由于

1 个答案:

答案 0 :(得分:2)

expand获取ID和年份的所有组合。然后再次left_join数据帧上的结果以获取x值。

require(dplyr)
require(tidyr) 
df <- data.frame(time = sample(2001:2012,12,replace = F),
                ID = sample(LETTERS[1:3],12, replace =T),
                x = sample(10:50,12))


df %>% 
  expand(time,ID) %>% 
  left_join(df, c('time','ID')) %>% 
  mutate(x = ifelse(is.na(x),0,x))

结果:

# A tibble: 36 × 3
time     ID     x
<int> <fctr> <dbl>
2001      A     0
2001      B    39
2001      C     0
2002      A     0
2002      B     0
2002      C    24
2003      A    35
2003      B     0
2003      C     0
2004      A    47
# ... with 26 more rows

如果由于某种原因不是所有年份都在您的数据框中,您可以使用自定义值展开。

df %>% 
  expand(time = 2001:2012,ID) %>% 
  left_join(df, c('time','ID')) %>% 
  mutate(x = ifelse(is.na(x),0,x))