基于R中的因素(或如何避免R中的循环)在两个数据帧之间连接信息的有效方法

时间:2017-10-10 15:58:04

标签: r loops dataframe

我有两个大型数据框,一个名为Dates_only,另一个名为Values

   **Dates_only:**  
       ID    Quart_y  Quart
    1  1118  2017Q3   0.25
    2  1118  2017Q4   0.50
    3  1118  2018Q1   0.75
    4  1118  2018Q2   1.00
    5  1118  2018Q3   1.25
    6  1118  2018Q4   1.50
    7  1118  2019Q1   1.75
    8  1118  2019Q2   2.00
    9  1119  2017Q3   0.25
    10 1119  2017Q4   0.50
    11 1119  2018Q1   0.75
    12 1119  2018Q2   1.00
    13 1119  2018Q3   1.25
    14 1119  2018Q4   1.50
    15 1119  2019Q1   1.75
    16 1119  2019Q2   2.00
    17 13PP  2017Q3   0.25
    18 13PP  2017Q4   0.50
    19 13PP  2018Q1   0.75
    20 13PP  2018Q2   1.00
    21 13PP  2018Q3   1.25
    22 13PP  2018Q4   1.50
    23 13PP  2019Q1   1.75
    24 13PP  2019Q2   2.00

第二个数据集:

**Values**  
  ID   Day   Value
1  1118  0    7.6
2  1119  0    6.2
3  13PP  0    6.8
4  1118  0.14 7.1
5  1119  0.13 6.2
6  13PP  0.13 5.9
7  1118  0.20 6.8
8  1119  0.23 5.8
9  13PP  0.24 4.6
10 1118  0.27 6.5
11 1119  0.28 5.4
12 13PP  0.32 4.2
13 1118  0.32 6.3
14 1119  0.32 4.8
15 13PP  0.44 4.0
16 1118  0.47 6.0
17 1119  0.49 4.3
18 13PP  0.49 3.8
19 1118  0.59 5.9
20 1119  0.64 4.0
21 13PP  0.61 3.6
22 1118  0.72 5.6
23 1119  0.71 3.8
24 13PP  0.73 3.4
25 1118  0.95 5.4
26 1119  0.86 3.2
27 13PP  0.78 3.0
28 1118  1.10 5.0
29 1119  0.93 2.9
30 13PP  1.15 2.9

我想要做的是在名为Dates_only的{​​{1}}中创建另一个列(第四个),它将包含从列{Value_average数据框中提取的平均分数1}}。 具体而言,您可以在ValuesValues$Value表示季度/年,Dates_only使用Quart_y中的数字对此进行量化。 所以,模式就像这样Quart

在第二个数据框0.25:2中,我们有一些分数代表一年中的几天。该概念是,对于分数Q3 - x.25, Q4 - x.50, Q1 - x.75, Q2 - x.00属于Values的天数,分数0<Day<0.25的天数属于2017Q3,分数0.25<Day<0.50的天数属于2017Q4 1.00<Day<1.25

我希望2018Q3数据框中的每个ID都能找到属于相应时间范围的Dates_only个数字的平均值: 适用于Values$ValueID=1118价值$ Day&#39; 2017Q3之间的元素0<Day<=0.25和等效的(0, 0.14, 0.20)之间的元素都是Values$Value,因此(7.6, 7.1, 6.8)将是Dates_only$Value_average。接下来将是天7.16等的平均值。

0.25<Day<=0.50

我使用的代码是:

   **Dates_only:**  
       ID    Quart_y  Quart Value_average
    1  1118  2017Q3   0.25   7.16
    2  1118  2017Q3   0.50   6.27

在非常大的数据集中是否有更高效的代码(超过300K观测值)?我很确定有,但我对R的新手技能没有多大帮助。

复制两个数据帧:

Dates_only$Value_average <- 0

for (i in 1:length(Dates_only$ID)){
  id <- as.character(Dates_only$ID[i])
  quart <- as.numeric(Dates_only$Quart[i])
  quart_prev <- quart-0.25

  count_d <- 0
  sum_val <- 0

  for (k in 1:length(Values$ID)){
    if (id==as.character(Values$ID[k]) 
        && quart>=as.numeric(Values$Day[k]) 
        && as.numeric(Values$Day[k])>quart_prev){
      sum_val <- as.numeric(Values$Value[k]) + sum_val 
      count_d <- count_d + 1
    }
  }
  av_value <- sum_val/count_d
  Dates_only$Value_average[i] <- av_value
}

1 个答案:

答案 0 :(得分:1)

我们可以使用dplyr

完成几乎所有这些操作
library(dplyr)

Values %>% 
  mutate(Day = ifelse(Day == 0, 0.01, Day)) %>% 
  mutate(Quart = ceiling(Day / 0.25) * 0.25) %>% 
  full_join(., Dates_only, by = c("ID", "Quart")) %>% 
  group_by(ID, Quart, Quart_y) %>% 
  summarise(Value_average = mean(Value, na.rm = TRUE))

这给了你:

       ID Quart Quart_y Value_average
   <fctr> <dbl>  <fctr>         <dbl>
 1   1118  0.25  2017Q3      7.166667
 2   1118  0.50  2017Q4      6.266667
 3   1118  0.75  2018Q1      5.750000
 4   1118  1.00  2018Q2      5.400000
 5   1118  1.25  2018Q3      5.000000
 6   1118  1.50  2018Q4           NaN
 7   1118  1.75  2019Q1           NaN
 8   1118  2.00  2019Q2           NaN
 9   1119  0.25  2017Q3      6.066667
10   1119  0.50  2017Q4      4.833333
# ... with 14 more rows

请参阅下文,了解任何问题的每行代码细分:

# Start with your `Values` data frame
Values %>% 
  # Recode `Day` that are '0.00', as they currently will be excluded from 
  # the rule 2017Q3: 0<Day<=0.25
  # I picked 0.01 arbitrarily to fit this rule
  mutate(Day = ifelse(Day == 0, 0.01, Day)) %>% 
  # Now round all `Day` values up to the nearest 0.25
  mutate(Quart = ceiling(Day / 0.25) * 0.25) %>% 
  # Now join the two data frames using a `full_join`
  # A left_join may also be used if you are uninterested in NA's
  full_join(., Dates_only, by = c("ID", "Quart")) %>% 
  # Finally, designate groupings to calculate the mean values 
  # for each ID for each quarter
  group_by(ID, Quart, Quart_y) %>% 
  summarise(Value_average = mean(Value, na.rm = TRUE))