在R中找出每日数据与月度数据的百分比差异

问题描述 投票:0回答:2

我想知道在不同地点每日平均温度与指定月平均值的差异。我在想这个百分比差异值。例如,指定的月平均值为20,我有几天是15(-25%),25(+ 25%)和10(-50%)。

我能想到的唯一方法是创建一个重复列,每个位置使用月度平均值,然后使用diff函数或百分比差异公式计算列之间的差异。我想知道是否有更优雅,更简单的方法来做这个适合大数据?

然后,我想要使用这个每日趋势或差异,并将其应用于一组不同的月度方法,将其分解为每日数据。例如,假设月平均值为10,我有几天的趋势是+ 25%(12.5), - 50%(5)和-25%(7.5)。再一次,有一种优雅或更简单的方法吗?

任何帮助,将不胜感激。我还是R的新手!

以下是一些示例数据:

Sample data

date <- c("2009-01-01", "2009-01-02", "2009-01-03", "2009-01-04","2009-01-05",
          "2009-01-01", "2009-01-02", "2009-01-03", "2009-01-04","2009-01-05",
          "2009-01-01", "2009-01-02", "2009-01-03", "2009-01-04","2009-01-05")

location <- c("A", "A", "A", "A", "A", 
           "B", "B", "B", "B", "B",
           "C", "C", "C", "C", "C")

daily_temp <- c(10, 12, 12, 9, 8,
               13, 14, 18, 8, 11,
               14, 18, 20, 16, 17)

data_daily <- cbind(date, location, daily_temp)

mean_monthly <- c(12, 14, 16)

location_monthly <- c("A", "B", "C")

data_monthly <- cbind(mean_monthly, location_monthly)
r diff
2个回答
1
投票

使源数据以正确的格式进行分析

df.daily <- as.data.frame( data_daily, stringsAsFactors = F)
df.monthly <- as.data.frame( data_monthly, stringsAsFactors = F)

tidyverse

library( tidyverse )

df.daily <- as.data.frame( data_daily, stringsAsFactors = FALSE )
df.monthly <- as.data.frame( data_monthly, stringsAsFactors = FALSE )

df.daily %>% 
  left_join( df.monthly, by = c( "location" = "location_monthly" ) ) %>%
  mutate( daily_temp = as.numeric( daily_temp ) ) %>%
  mutate( mean_monthly = as.numeric( mean_monthly ) ) %>%
  mutate( delta_temp = ( daily_temp - mean_monthly ) / mean_monthly )

#          date location daily_temp mean_monthly  delta_temp
# 1  2009-01-01        A         10           12 -0.16666667
# 2  2009-01-02        A         12           12  0.00000000
# 3  2009-01-03        A         12           12  0.00000000
# 4  2009-01-04        A          9           12 -0.25000000
# 5  2009-01-05        A          8           12 -0.33333333
# 6  2009-01-01        B         13           14 -0.07142857
# 7  2009-01-02        B         14           14  0.00000000
# 8  2009-01-03        B         18           14  0.28571429
# 9  2009-01-04        B          8           14 -0.42857143
# 10 2009-01-05        B         11           14 -0.21428571
# 11 2009-01-01        C         14           16 -0.12500000
# 12 2009-01-02        C         18           16  0.12500000
# 13 2009-01-03        C         20           16  0.25000000
# 14 2009-01-04        C         16           16  0.00000000
# 15 2009-01-05        C         17           16  0.06250000

data.table

#less readable but usually faster , especially on larger datasets
library( data.table )

setDT( df.monthly )[, mean_monthly := as.numeric( mean_monthly )][setDT( df.daily )[, daily_temp := as.numeric( daily_temp )], on = c( "location_monthly==location" )][, delta_temp := ( daily_temp - mean_monthly ) / mean_monthly ][]

基准

data.table略有优势

microbenchmark::microbenchmark( tidyverse = {df.daily %>% 
    left_join( df.monthly, by = c( "location" = "location_monthly" ) ) %>%
    mutate( daily_temp = as.numeric( daily_temp ) ) %>%
    mutate( mean_monthly = as.numeric( mean_monthly ) ) %>%
    mutate( delta_temp = ( daily_temp - mean_monthly ) / mean_monthly )},
    data.table = {setDT(df.monthly)[, mean_monthly := as.numeric( mean_monthly )][setDT(df.daily)[, daily_temp := as.numeric( daily_temp )], on = c( "location_monthly==location" )][, delta_temp := ( daily_temp - mean_monthly ) / mean_monthly ][]},
    times = 100)

# Unit: milliseconds
# expr            min       lq     mean   median       uq       max neval
# tidyverse  2.318527 2.408303 2.579056 2.454999 2.513293 13.104373   100
# data.table 1.515959 1.590221 1.669511 1.643545 1.702141  2.345037   100

1
投票

基于@ Wimpel的回应,以下是一些总结位置差异的方法。

df.combo <-
  df.daily%>% 
  left_join( df.monthly, by = c( "location" = "location_monthly" ) ) %>%
  mutate( daily_temp = as.numeric( daily_temp ) ) %>%
  mutate( mean_monthly = as.numeric( mean_monthly ) ) %>%
  mutate( delta_temp = ( daily_temp - mean_monthly ) / mean_monthly ) %>%

  # Here I add the difference in degrees between daily temp and monthly avg temp
  mutate( temp_dif = daily_temp - mean_monthly)

# For each location, what are some stats about those temp_dif values?
df.loc.stats <-
  df.combo %>% 
  group_by(location) %>%
  summarize(mean_dif = mean(temp_dif),
            mean_abs_dif = mean(abs(temp_dif)),
            SD_dif = sd(temp_dif))

df.loc.stats表显示位置B具有最多变化的温度(例如,使用平均绝对差异或标准偏差测量),而A在平均温度下最低且C最高:

df.loc.stats
# A tibble: 3 x 4
  location mean_dif mean_abs_dif SD_dif
  <chr>       <dbl>        <dbl>  <dbl>
1 A            -1.8          1.8   1.79
2 B            -1.2          2.8   3.70
3 C             1            1.8   2.24
© www.soinside.com 2019 - 2024. All rights reserved.