【问题标题】:new column based on two rows from consecutive days in R基于R中连续几天的两行的新列
【发布时间】:2021-05-06 15:20:37
【问题描述】:

我有以下问题。 我计算了每个国家的平均温度,以及实际每日温度和平均温度之间的差异。见以下代码:

df1 <- data.frame(country = c("01", "01", "01","01", "01", "02", "02" , "03", "03","03"),
                  date = c("2020-01-01", "2020-01-02", "2020-01-03" , "2020-01-05", "2020-01-07", "2020-01-01", "2020-01-03", "2020-01-02",  "2020-01-03", "2020-01-04"),
                  temperature = c(4, 3, -2, 0.1, -3, 1.5, 12, 10, 7, 5),
                  blabla = c(23, 41, 32, 8, 50, 27, 8, 7, 6, 12)
)


library(dplyr)

df2 <- df1 %>%
  group_by(country) %>%
  mutate(mean_per_country = mean(temperature))


df2$difference <- df2$temperature - df2$mean_per_country

现在我需要创建一个新列来检查同一国家/地区的连续天数是否(不限)在实际每日温度和平均温度之间存在负差或正差。有没有一种优雅的方法可以在 R 中做到这一点?

想要的输出在这里:

desired_df <- data.frame(country = c("01", "01", "01","01", "01", "02", "02" , "03", "03","03"),
                         date = c("2020-01-01", "2020-01-02", "2020-01-03" , "2020-01-05", "2020-01-07", "2020-01-01", "2020-01-03", "2020-01-02",  "2020-01-03", "2020-01-04"),
                         temperature = c(4, 3, -2, 2, -3, 1.5, 12, 10, 7, 5),
                         blabla = c(23, 41, 32, 8, 50, 27, 8, 7, 6, 12),
                         mean_per_country = c(0.42, 0.42, 0.42, 0.42, 0.42, 6.75, 6.75, 7.33, 7.33, 7.33),
                         difference = c(3.58, 2.58, -2.42 , -0.32, -3.42 , -5.25, 5.25, 2.67, -0.333, -2.33),
                         new_column = c("hot",
                                        "hot",
                                        "", #day interrupted, therefor not "cold"
                                        "", #day interrupted, therefor not "cold"
                                        "", #day interrupted, therefor not "cold"
                                        "", 
                                        "", 
                                        "", 
                                        "cold",
                                        "cold")
                         
)

非常感谢

【问题讨论】:

  • 为什么国家01有两天热,而不是三天冷。同理,为什么03有两天冷,没有一天热?
  • @IanCampbell 因为国家 01 在 2020-01-01 和 2020-01-02 有一个积极的difference。后来,2020-01-03 和 2020-01-05 不是连续的日子,因为缺少 2020-01-04,因此没有cold。同样,2020-01-01 中没有国家 03 的数据,因此 2020-01-02 不能是hot。现在清楚了吗?
  • 感谢您的澄清。

标签: r dplyr


【解决方案1】:

这是dplyr 的一种方法:

library(dplyr)
df2 %>%
   group_by(country) %>%
   mutate(date = as.Date(date),
          consecutive = date - lag(date) == 1,
          result = (sign(difference) == sign(lead(difference)) & lead(consecutive) |
                   (sign(difference) == sign(lag(difference)) & consecutive)),
          new_column = c("cold",NA_character_,"hot")[result * sign(difference) + 2])
# A tibble: 10 x 9
# Groups:   country [3]
   country date       temperature blabla mean_per_country difference consecutive result new_column
   <chr>   <date>           <dbl>  <dbl>            <dbl>      <dbl> <lgl>       <lgl>  <chr>     
 1 01      2020-01-01         4       23             0.42      3.58  NA          TRUE   hot       
 2 01      2020-01-02         3       41             0.42      2.58  TRUE        TRUE   hot       
 3 01      2020-01-03        -2       32             0.42     -2.42  TRUE        FALSE  NA        
 4 01      2020-01-05         0.1      8             0.42     -0.32  FALSE       FALSE  NA        
 5 01      2020-01-07        -3       50             0.42     -3.42  FALSE       NA     NA        
 6 02      2020-01-01         1.5     27             6.75     -5.25  NA          NA     NA        
 7 02      2020-01-03        12        8             6.75      5.25  FALSE       NA     NA        
 8 03      2020-01-02        10        7             7.33      2.67  NA          NA     NA        
 9 03      2020-01-03         7        6             7.33     -0.333 TRUE        TRUE   cold      
10 03      2020-01-04         5       12             7.33     -2.33  TRUE        TRUE   cold      

为了摆脱我为说明目的而留在那里的中间列,只需用户 select(-(consecutive:result))

【讨论】:

    【解决方案2】:

    您需要将日期转换为Date 类,然后您可以计算日期之间的差异。然后按国家分组,如果差异为 1,则使用ifelse() 设置值:

    require(plyr)
    require(dplyr)
    df2$date = as.Date(df2$date)
    diffs <- c(0,diff(df2$date))
    df2 %>% group_by(country) %>%
            plyr::mutate(new_column = ifelse((difference > 0) & (diffs == 1), "hot", ifelse((difference < 0) & (diffs == 1), "cold", " ")))
    
    > df2
       country       date temperature blabla mean_per_country difference new_column
    1       01 2020-01-01         4.0     23         0.420000  3.5800000       
    2       01 2020-01-02         3.0     41         0.420000  2.5800000        hot
    3       01 2020-01-03        -2.0     32         0.420000 -2.4200000       cold
    4       01 2020-01-05         0.1      8         0.420000 -0.3200000           
    5       01 2020-01-07        -3.0     50         0.420000 -3.4200000           
    6       02 2020-01-01         1.5     27         6.750000 -5.2500000           
    7       02 2020-01-03        12.0      8         6.750000  5.2500000           
    8       03 2020-01-02        10.0      7         7.333333  2.6666667           
    9       03 2020-01-03         7.0      6         7.333333 -0.3333333       cold
    10      03 2020-01-04         5.0     12         7.333333 -2.3333333       cold
    

    【讨论】:

    • 感谢您的回答。但是为什么第一行是hot
    • 应该是什么?
    • @VitaminB16 空行,因为没有 2020-12-31 日期为正 difference
    • @IanCampbell 我的mutate() 函数与另一个库发生了冲突。现在修好了。 @vojtam 也改变了。
    • @vojtam 检查:您的desired_df 在第一行有hot
    猜你喜欢
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 2014-07-25
    • 2018-08-04
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 2022-11-25
    相关资源
    最近更新 更多