【问题标题】:R: Add interpolated values in between columns of dataframe?R:在数据框的列之间添加插值?
【发布时间】:2020-01-11 14:16:02
【问题描述】:

我有一个看起来像这样的数据框

Region      2000    2001   2002    2003    2004      2005
Australia   15.6    18.4   19.2    20.2    39.1      50.2
Norway      19.05   20.2   15.3    10      10.1      5.6

基本上我需要一种快速的方法来在当前存在的包含周围列的插值的列之间添加额外的列。

可以这样想:假设您不想要每一年的列,而是每季度的列。然后,对于每一年(如 2000 年和 2001 年),我们需要在这些年之间添加 3 个额外的列。

这些列的值将只是插值。因此,对于澳大利亚,2000 年的值为 15.6,而 2001 年为 18.4。所以我们计算 (18.4 - 15.6)/4 = 0.7,然后这些值现在应该是 15.6、16.3、17、17.7,最后是 18.4。

我有一个可行的解决方案,它使用 for 循环从头开始构建新的数据框。它非常慢。如何加快速度?

【问题讨论】:

  • DF可以转置吗?

标签: r


【解决方案1】:

当我遇到类似问题时,我就是这样做的。不是最复杂的解决方案,但它确实有效。

Australia=c(  15.6,  18.4,  19.2,  20.2,   39.1,     50.2)

library(zoo)
midpoints=rollmean(Australia, 2)
biyearly=c(rbind(Australia,midpoints))
midpoints=rollmean(biyearly, 2)
quarterly=c(rbind(biyearly,midpoints))
quarterly
#[1] 15.600 16.300 17.000 17.700 18.400 18.600 18.800 19.000 19.200 19.450 19.700
#[12] 19.950 20.200 24.925 29.650 34.375 39.100 41.875 44.650 47.425 50.200 33.600
#[23] 17.000 16.300

【讨论】:

    【解决方案2】:

    这是一个使用 dplyr 的解决方案。应该比循环更一致且更快:

    # dummy data
    df <- tibble(Region = LETTERS[1:5],
                 `2000` = 1:5,
                 `2001` = 3:7,
                 `2002` = 10:14)
    
    # function to calculate quarterly values
    into_quarter <- function(x) x / 4
    
    df %>% 
      # create new variables that contain quarterly values
      mutate_at(vars(starts_with("200")), 
                .funs = list("Q1" = into_quarter,
                             "Q2" = into_quarter,
                             "Q3" = into_quarter,
                             "Q4" = into_quarter)) %>% 
      # sort them approriatly.
      # can also be done with base R and order(names), depending on desired result
      select(Region, 
             starts_with("2000"),
             starts_with("2001"),
             starts_with("2002"),
             # in case there are also other variables and to not loose any information
             everything())
    

    【讨论】:

      【解决方案3】:

      这是tidyverse的一种方式:

      library(tidyverse)
      
      df %>%
        #get data in long format
        pivot_longer(cols = -Region) %>%
        #group by Region
        group_by(Region) %>%
        #Create 4 number sequence between every 2 value
        summarise(temp = list(unlist(map2(value[-n()], value[-1], seq, length.out = 4)))) %>%
        #Get data in long format
        unnest(temp) %>%
        group_by(Region) %>%
        #Create column name
        mutate(col = paste0(rep(names(df)[-c(1, ncol(df))], each = 4), "Q", 1:4)) %>%
        #Spread data in wide format
        pivot_wider(names_from = col, values_from = temp)
      
      # A tibble: 2 x 21
      # Groups:   Region [2]
      #  Region `2000Q1` `2000Q2` `2000Q3` `2000Q4` `2001Q1` `2001Q2` `2001Q3` `2001Q4` `2002Q1`
      #  <fct>     <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
      #1 Austr…     15.6     16.5     17.5     18.4     18.4     18.7     18.9     19.2     19.2
      #2 Norway     19.0     19.4     19.8     20.2     20.2     18.6     16.9     15.3     15.3
      # … with 11 more variables: `2002Q2` <dbl>, `2002Q3` <dbl>, `2002Q4` <dbl>,
      #   `2003Q1` <dbl>, `2003Q2` <dbl>, `2003Q3` <dbl>, `2003Q4` <dbl>, `2004Q1` <dbl>,
      #   `2004Q2` <dbl>, `2004Q3` <dbl>, `2004Q4` <dbl>
      

      数据

      df <- structure(list(Region = structure(1:2, .Label = c("Australia", 
      "Norway"), class = "factor"), `2000` = c(15.6, 19.05), `2001` = c(18.4, 
      20.2), `2002` = c(19.2, 15.3), `2003` = c(20.2, 10), `2004` = c(39.1, 
      10.1), `2005` = c(50.2, 5.6)), class = "data.frame", row.names = c(NA, -2L))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-18
        • 1970-01-01
        • 1970-01-01
        • 2014-06-03
        • 1970-01-01
        • 2017-06-17
        • 1970-01-01
        相关资源
        最近更新 更多