我有一个降水数据库,它的结构如下。
Season; YEAR; MONTH; DAY 01; DAY 02; DAY 03 ..... DAY 31 一开始,我想计算每个月的累积(我使用了精确度),但只计算了一个季节。现在我想做同样的事情,但要分离每个工作站,除了更改数据库的结构之外,我还将获得每个工作站的每日和每月值。其中第一列是日期,其他列是每个季节。
Date; season1; station2; estacao3 ....... estacaoN
01/01/1994;30;10;5;6
01/02/1994;10;12;55
.
.
.
.
.
.
.
31/07/2018发布于 2020-01-25 01:50:04
此任务需要对数据集进行一些整形,首先将其变长,然后再将其变宽。DC37的答案已经描述了如何使用data.table来做到这一点。我推荐一种稍微不同的方法,只使用tidyverse函数。
您声明,您希望计算每个站点每月的降雨量总和,对于该任务,实际上更容易将数据保存为较长的格式,而不是再次使其变宽。下面我将演示这两个选项(2a和2b)。
我还建议不要合并日期变量,因为这会使按月分组数据变得更加困难,或者,对于我的方法,您可以只合并年和月,这样仍然可以进行必要的分组。总之,2a)演示了如何使用tidyr::unite()来合并日期变量。
1)将数据集转换为长格式
library(tidyverse)
library(readxl)
rainfall_df <- read_excel("Dados_precipitacao.xls", skip = 2)
rainfall_long_df <-
rainfall_df %>%
select(-Bacia) %>%
pivot_longer(`dia 1`:`dia 31`, names_to = "dia") %>%
mutate(dia = gsub("dia ", "", dia))rainfall_long_df看起来像这样:
# A tibble: 1,931,889 x 5
`Município/Posto` Ano Mês dia value
<chr> <dbl> <dbl> <chr> <dbl>
1 Agua Branca 1994 1 1 0
2 Agua Branca 1994 1 2 0
3 Agua Branca 1994 1 3 0
4 Agua Branca 1994 1 4 0
5 Agua Branca 1994 1 5 0
6 Agua Branca 1994 1 6 8.6
7 Agua Branca 1994 1 7 0
8 Agua Branca 1994 1 8 2
9 Agua Branca 1994 1 9 0
10 Agua Branca 1994 1 10 0
# … with 1,931,879 more rows2a)这就是您所要求的:从广泛的数据集中计算每月和站点的总和。
rainfall_wide_df <-
rainfall_long_df %>%
unite(data, dia, Mês, Ano, sep = "/", remove = FALSE) %>%
pivot_wider(names_from = `Município/Posto`)
rainfall_wide_df %>%
group_by(Ano, Mês) %>%
summarise_at(vars(`Agua Branca`:`Zabelê`), sum)这将导致:
# A tibble: 296 x 253
# Groups: Ano [26]
Ano Mês `Agua Branca` Aguiar `Alagoa Grande` `Alagoa Nova` Alagoinha Alcantil `Algodão de Jan…
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1994 1 174. 442. 101 68.5 64.6 NA NA
2 1994 2 NA NA NA NA NA NA NA
3 1994 3 285. 120. 239. 210. 213. NA NA
4 1994 4 NA NA NA NA NA NA NA
5 1994 5 176. 73.2 160. 233. 190 NA 41.8
6 1994 6 NA NA NA NA NA NA NA
7 1994 7 55.6 33.3 292. 188. 291. NA 51.4
8 1994 8 28 0 60.8 68.1 57.6 NA 16.1
9 1994 9 NA NA NA NA NA NA NA
10 1994 10 20 0 8.8 9.3 3.6 NA 0
# … with 286 more rows, and 244 more variables2b)这是获得每个站点和月份的总和的另一种解决方案。它更容易用于后续步骤(特别是在ggplot2中的可视化)。我也觉得,代码更直接了!
rainfall_long_df %>%
group_by(`Município/Posto`, Ano, Mês) %>%
summarise(rainfall_per_month = sum(value))结果将是每个月和站点的降雨量总和的长期版本。
# A tibble: 62,319 x 4
# Groups: Município/Posto, Ano [5,522]
`Município/Posto` Ano Mês rainfall_per_month
<chr> <dbl> <dbl> <dbl>
1 Agua Branca 1994 1 174.
2 Agua Branca 1994 2 NA
3 Agua Branca 1994 3 285.
4 Agua Branca 1994 4 NA
5 Agua Branca 1994 5 176.
6 Agua Branca 1994 6 NA
7 Agua Branca 1994 7 55.6
8 Agua Branca 1994 8 28
9 Agua Branca 1994 9 NA
10 Agua Branca 1994 10 20
# … with 62,309 more rows发布于 2020-01-25 01:05:17
首先,由于您的数据帧相当重(我只在其中的一部分上运行代码),您可以使用data.table中的fread函数打开它(我将您的xlsx文件转换为csv文件)。
library(data.table)
df <- fread("../Dados_precipitacao.csv", skip = 2, header = TRUE)然后,您可以使用data.table中的melt函数以long格式整形数据帧
library(data.table)
colonne <- grep("dia",colnames(df),value = TRUE)
dt.m <- melt(df, measure = list(colonne),value.name = "DIA")现在,您有六列:
Município/Posto Bacia Ano Mês variable DIA
1: Agua Branca Piancó 1994 1 dia 1 0
2: Agua Branca Piancó 1994 2 dia 1 0
3: Agua Branca Piancó 1994 3 dia 1 20
4: Agua Branca Piancó 1994 4 dia 1 0
5: Agua Branca Piancó 1994 5 dia 1 0
6: Agua Branca Piancó 1994 6 dia 1 0现在,使用data.table,我们可以通过粘贴Ano、Mes和Dia来创建日期列(Dia将被修改以从字符串中删除"dia“),然后,我们将使用lubridate包中的ymd函数将此字符串转换为数据格式:
library(data.table)
test <- dt.m[1:1000,]
test[, Day:=gsub("dia ","",variable)]
test[, Date := do.call(paste, c(.SD, sep = "-")), .SDcols = c("Ano","Mês","Day")]
test[, Date:= ymd(Date)]
Município/Posto Bacia Ano Mês variable DIA Day Date
1: Agua Branca Piancó 1994 1 dia 1 0 1 1994-01-01
2: Agua Branca Piancó 1994 2 dia 1 0 1 1994-02-01
3: Agua Branca Piancó 1994 3 dia 1 20 1 1994-03-01
4: Agua Branca Piancó 1994 4 dia 1 0 1 1994-04-01
5: Agua Branca Piancó 1994 5 dia 1 0 1 1994-05-01
---
996: Alagoa Nova Mamanguape 2003 8 dia 1 0 1 2003-08-01
997: Alagoa Nova Mamanguape 2003 9 dia 1 0 1 2003-09-01
998: Alagoa Nova Mamanguape 2003 10 dia 1 0 1 2003-10-01
999: Alagoa Nova Mamanguape 2003 11 dia 1 0 1 2003-11-01
1000: Alagoa Nova Mamanguape 2003 12 dia 1 0 1 2003-12-01现在,我们可以使用data.table中的函数dcast以更宽的格式透视数据表,并为每个站点创建一列(这里我使用了Municipio/Posto):
library(data.table)
t <- dcast(test, value.var = "DIA", ... ~ `Município/Posto`)
Bacia Ano Mês variable Day Date Agua Branca Aguiar Alagoa Grande Alagoa Nova
1: Mamanguape 1994 1 dia 1 1 1994-01-01 NA NA 0 0
2: Mamanguape 1994 2 dia 1 1 1994-02-01 NA NA 0 0
3: Mamanguape 1994 3 dia 1 1 1994-03-01 NA NA 0 0
4: Mamanguape 1994 4 dia 1 1 1994-04-01 NA NA 0 0
5: Mamanguape 1994 5 dia 1 1 1994-05-01 NA NA 0 0
---
584: Piancó 2018 3 dia 1 1 2018-03-01 5.4 0 NA NA
585: Piancó 2018 4 dia 1 1 2018-04-01 12.6 0 NA NA
586: Piancó 2018 5 dia 1 1 2018-05-01 15.8 NA NA NA
587: Piancó 2018 6 dia 1 1 2018-06-01 0.0 NA NA NA
588: Piancó 2018 7 dia 1 1 2018-07-01 0.0 NA NA NA希望这就是你正在寻找的东西。
顺便说一句:如果你发布一个可复制的数据示例,而不是插入一个指向整个数据集的链接(这是相当繁重的),这将使每个人的事情变得更容易。要知道如何做一个好的可重现的例子:How to make a great R reproducible example
发布于 2020-01-25 06:32:46
首先,我想感谢您的回复。其次,我很抱歉这个问题没有在正确的结构中(我第一次在这里),我对R的宇宙也是新的。我正在使用这些数据作为水文学研究的一部分,这个结构对于使用HydroTSM软件包和后来的特种部队是必要的。
我做了推荐的测试,但出现了一些问题。我的问题都得到了解决。但是,我意识到在创建日期时,闰年有一个小问题,但是我手动删除了这些日期。
在建立数据库时,您应该如何考虑闰年?
谢谢。
https://stackoverflow.com/questions/59900449
复制相似问题