台灣電力交易資料

Taipower Historical Settlement Trading

WebScraping from 2021/11/26

在台灣電力公司的電力交易平台中,日前輔助服務市場項目中有歷史結清價格與交易量資料。電力的項目分為即時備轉以及補充備轉,得標的單位分為國營與民間,或者非交易的得標容量,而非交易的暫不考慮。而結清價格與得標容量以小時為單位,因此每一小時有即時備轉得標容量(國營)、即時備轉得標容量(民營)、即時備轉結清價格、補充備轉得標容量(國營)、補充備轉得標容量(民營)、補充備轉結清價格六筆資料。資料自2021年11月26日開始每日更新。連結為https://etp.taipower.com.tw/web/service_market/historical_settlement_trading

而在歷史結清價格與交易量的頁面只有每日以得標容量形成的堆疊柱狀圖加上結清價格的折線圖,滑鼠移至點上會出現容量和價格數字,目的是抓取所有的數字。在網頁前端內中有所有歷史數據,在JavaScript架構下以JSON格式儲存,目標是將資料抓取後轉成R資料格式再輸出,並且計算每日總得標容量以及每月平均電價。

Packages

rvest是使用R進行網路爬蟲中重要的套件,jsonlite套件可以操作json格式的資料,lubridate可以進行日期時間格式的轉換,openxlsx可以操作excel檔案。

library(rvest) 
library(magrittr) 
library(jsonlite) 
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(lubridate) 
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(openxlsx)

Webscraping

電力交易平台儲存資料的位置是網址+日期,因此需要自開始日至今日天數個網址,再進行迭代。

Create date and variables

首先生成一個從2021/11/16至今天的字串向量。date()會將括號內的字串轉換成日期格式,Sys.Date()會返回當前系統的日期,seq()會建立序列,需要指定開始、結尾、間隔,如下表示自2021/11/16開始自今天建立序列,間隔為一天。此時生成的向量格式為日期,使用as.character()將日期轉換成字串,儲存為名為dat的物件。

date("2021-11-16")
## [1] "2021-11-16"
Sys.Date()
## [1] "2023-02-03"
head(seq(from = date('2021-11-16'), to = Sys.Date(), by = 1))
## [1] "2021-11-16" "2021-11-17" "2021-11-18" "2021-11-19" "2021-11-20"
## [6] "2021-11-21"
dat <- as.character(
  seq(from = date("2021-11-16"), to = Sys.Date(), by = 1))

head(dat)
## [1] "2021-11-16" "2021-11-17" "2021-11-18" "2021-11-19" "2021-11-20"
## [6] "2021-11-21"

在稍後抓取的資料中,需要選取我們需要的變量,因此先創立需要變量的向量,方便選取。datetime是日期時間,sr是即時備轉,sup字首是補充備轉,Bid字尾是得標容量(國營),BidQse是得標容量(民營),price是結清價格。得標容量的單位都是百萬瓦(MW),而價格的單位是百萬瓦/小時(元/MW·h)。

var <- c("datetime", "srBid", "srBidQse", "srPrice", "supBid", "supBidQse", "supPrice")

為了儲存下載的資料,我們創立一個空物件df用來儲存。

df <- NULL

Example

由於迭代的過程不易理解其中的步驟,因此我們先用2021/11/16為例,了解整個爬蟲以及資料轉換的過程後,再使用迭代方式,其實R更方便進行操作的方式是使用apply家族的函數運算,但方式稍微抽象,因此未來有機會再說明。

url為我們要查詢的網址位置,為固定內容加上要查詢的日期,可以直接將該網址使用瀏覽器查詢,https://etp.taipower.com.tw/api/infoboard/settle_value/query?startDate=2021-11-16,可以直接到該為止,在軟體中,url多代表想要查詢的位置。

url <- paste0("https://etp.taipower.com.tw/api/infoboard/settle_value/query?startDate=",
              as.character(date('2021-11-16')))

url
## [1] "https://etp.taipower.com.tw/api/infoboard/settle_value/query?startDate=2021-11-16"

使用rvest套件中的read_html()讀取網頁,網頁是由許多節點組成,下列出現我們最初讀取到的內容。我們想要的是在節點p下的data物件。

read_html(url)
## {html_document}
## <html>
## [1] <body><p>{"msg":"操作成功","code":200,"data":[{"tranDate":"2021-11-16","tranH ...
read_html(url) %>% 
  html_nodes('p')
## {xml_nodeset (1)}
## [1] <p>{"msg":"操作成功","code":200,"data":[{"tranDate":"2021-11-16","tranHour":" ...

接下來我們想要將節點內的東西轉成R的dataframe格式,先用html_text()將網頁內容轉成文字格式,再用fromJSONjson格式方式轉換。

read_html(url) %>% 
  html_nodes('p') %>% 
  html_text %>% 
  fromJSON()
## $msg
## [1] "操作成功"
## 
## $code
## [1] 200
## 
## $data
##      tranDate tranHour marginalPrice regBid regBidQse regBidNontrade regDemand
## 1  2021-11-16    00:00      2447.016  105.0        14          681.0       500
## 2  2021-11-16    01:00      2413.235  105.0        14          681.0       500
## 3  2021-11-16    02:00      2273.417  105.0        14          681.0       500
## 4  2021-11-16    03:00      2199.381  281.0        14          505.0       500
## 5  2021-11-16    04:00      2413.235  281.0        14          505.0       500
## 6  2021-11-16    05:00      2290.265  281.0        14          505.0       500
## 7  2021-11-16    06:00      2273.417  281.0        14          505.0       500
## 8  2021-11-16    07:00      2343.366  281.0        14          505.0       500
## 9  2021-11-16    08:00      2473.417  219.4        14          566.8       500
## 10 2021-11-16    09:00      2752.809   80.0        14          706.1       500
## 11 2021-11-16    10:00      2647.016   80.0        14          706.1       500
## 12 2021-11-16    11:00      2879.899   80.0        14          706.1       500
## 13 2021-11-16    12:00      2647.016  108.9        14          677.3       500
## 14 2021-11-16    13:00      2794.398   80.0        14          706.1       500
## 15 2021-11-16    14:00      3556.155   80.0        14          706.2       500
## 16 2021-11-16    15:00      4010.084   80.0        14          706.2       500
## 17 2021-11-16    16:00      4101.844   80.0        14          706.2       500
## 18 2021-11-16    17:00      4101.844   80.0        14          706.3       500
## 19 2021-11-16    18:00      4101.844   80.0        14          706.2       500
## 20 2021-11-16    19:00      4101.844   80.0        14          706.3       500
## 21 2021-11-16    20:00      4101.844   80.0        14          706.2       500
## 22 2021-11-16    21:00      4101.844   80.0        14          706.1       500
## 23 2021-11-16    22:00      3892.572   92.6        14          693.6       500
## 24 2021-11-16    23:00      3724.364   80.0        14          706.0       500
##    regOffering regPrice regRegistered srBid srBidQse srBidNontrade srDemand
## 1       1232.9      550       31498.9 376.0        1         623.0      500
## 2       1232.9      550       31498.9 346.0        1         653.0      500
## 3       1232.9      550       31498.9 254.0        1         745.0      500
## 4       1232.9      600       31498.9 363.0        1         636.0      500
## 5       1232.9      600       31498.9 346.0        1         653.0      500
## 6       1232.9      600       31498.9 361.2        1         638.0      500
## 7       1232.9      600       31498.9 363.0        1         636.1      500
## 8       1232.9      600       31498.9 346.0        1         653.0      500
## 9       1232.9      600       31498.9 401.6        1         597.6      500
## 10      1232.9      595       31498.9 340.0        1         659.0      500
## 11      1232.9      595       31498.9 376.0        1         623.1      500
## 12      1232.9      595       31498.9 320.3        0         679.9      500
## 13      1232.9      600       31498.9 415.0        0         585.2      500
## 14      1232.9      595       31498.9 376.0        0         624.0      500
## 15      1232.9      595       31498.9 350.0        1         649.0      500
## 16      1232.9      600       31498.9 310.0        1         689.0      500
## 17      1232.9      595       31498.9 307.3        1         691.8      500
## 18      1232.9      595       31498.9 307.3        1         691.9      500
## 19      1232.9      595       31498.9 307.3        1         692.1      500
## 20      1232.9      595       31498.9 307.3        1         692.0      500
## 21      1232.9      595       31498.9 307.3        1         691.9      500
## 22      1232.9      595       31498.9 310.0        1         689.2      500
## 23      1232.9      600       31498.9 310.0        1         689.0      500
## 24      1232.9      600       31498.9 350.0        1         649.1      500
##    srOffering srPrice srRegistered supBid supBidQse supBidNontrade supDemand
## 1    4854.444     400     10215.64  869.7         0          130.5      1000
## 2    4854.444     400     10215.64  823.1         0          177.2      1000
## 3    4854.444     400     10215.64  809.4         0          190.9      1000
## 4    4854.444     400     10215.64  759.3         0          241.2      1000
## 5    4854.444     400     10215.64  739.9         0          260.7      1000
## 6    4854.444     400     10215.64  844.5         0          155.9      1000
## 7    4854.444     400     10215.64  839.4         0          161.0      1000
## 8    4854.444     400     10215.64  685.4         0          315.1      1000
## 9    4854.444     400     10215.64  940.1         0           60.1      1000
## 10   4854.444     400     10215.64  872.2         0          127.9      1000
## 11   4854.444     400     10215.64  907.9         0           92.2      1000
## 12   4853.444     400     10215.64  915.2         0           84.9      1000
## 13   4853.444     400     10215.64  873.0         0          127.1      1000
## 14   4853.444     400     10215.64  922.2         0           78.0      1000
## 15   4854.444     400     10215.64  867.8         0          132.7      1000
## 16   4854.444     400     10215.64  893.3         0          107.0      1000
## 17   4854.444     400     10215.64  765.3         0          235.2      1000
## 18   4854.444     400     10215.64  856.3         0          144.1      1000
## 19   4829.444     400     10215.64  524.1         0           33.2      1000
## 20   4854.444     400     10215.64  859.4         0          140.7      1000
## 21   4854.444     400     10215.64  843.6         0          156.6      1000
## 22   4854.444     400     10215.64  991.6         0            8.6      1000
## 23   4854.444     400     10215.64  922.2         0           78.0      1000
## 24   4854.444     400     10215.64  902.6         0           97.5      1000
##    supOffering supPrice supRegistered
## 1     7437.194      350      14174.55
## 2     7437.194      350      14174.55
## 3     7437.194      350      14174.55
## 4     7437.194      350      14174.55
## 5     7437.194      350      14174.55
## 6     7437.194      350      14174.55
## 7     7437.194      350      14174.55
## 8     7437.194      350      14174.55
## 9     7437.194      350      14174.55
## 10    7437.194      350      14174.55
## 11    7437.194      350      14174.55
## 12    7437.194      350      14174.55
## 13    7437.194      350      14174.55
## 14    7437.194      350      14174.55
## 15    7437.194      350      14174.55
## 16    7437.194      350      14174.55
## 17    7437.194      350      14174.55
## 18    7437.194      350      14174.55
## 19    7397.194      350      14174.55
## 20    7437.194      350      14174.55
## 21    7437.194      350      14174.55
## 22    7437.194      350      14174.55
## 23    7437.194      350      14174.55
## 24    7437.194      350      14174.55

若是針對json檔案可以直接使用url進行查詢和轉換。

dfi <- fromJSON(url)

dfi
## $msg
## [1] "操作成功"
## 
## $code
## [1] 200
## 
## $data
##      tranDate tranHour marginalPrice regBid regBidQse regBidNontrade regDemand
## 1  2021-11-16    00:00      2447.016  105.0        14          681.0       500
## 2  2021-11-16    01:00      2413.235  105.0        14          681.0       500
## 3  2021-11-16    02:00      2273.417  105.0        14          681.0       500
## 4  2021-11-16    03:00      2199.381  281.0        14          505.0       500
## 5  2021-11-16    04:00      2413.235  281.0        14          505.0       500
## 6  2021-11-16    05:00      2290.265  281.0        14          505.0       500
## 7  2021-11-16    06:00      2273.417  281.0        14          505.0       500
## 8  2021-11-16    07:00      2343.366  281.0        14          505.0       500
## 9  2021-11-16    08:00      2473.417  219.4        14          566.8       500
## 10 2021-11-16    09:00      2752.809   80.0        14          706.1       500
## 11 2021-11-16    10:00      2647.016   80.0        14          706.1       500
## 12 2021-11-16    11:00      2879.899   80.0        14          706.1       500
## 13 2021-11-16    12:00      2647.016  108.9        14          677.3       500
## 14 2021-11-16    13:00      2794.398   80.0        14          706.1       500
## 15 2021-11-16    14:00      3556.155   80.0        14          706.2       500
## 16 2021-11-16    15:00      4010.084   80.0        14          706.2       500
## 17 2021-11-16    16:00      4101.844   80.0        14          706.2       500
## 18 2021-11-16    17:00      4101.844   80.0        14          706.3       500
## 19 2021-11-16    18:00      4101.844   80.0        14          706.2       500
## 20 2021-11-16    19:00      4101.844   80.0        14          706.3       500
## 21 2021-11-16    20:00      4101.844   80.0        14          706.2       500
## 22 2021-11-16    21:00      4101.844   80.0        14          706.1       500
## 23 2021-11-16    22:00      3892.572   92.6        14          693.6       500
## 24 2021-11-16    23:00      3724.364   80.0        14          706.0       500
##    regOffering regPrice regRegistered srBid srBidQse srBidNontrade srDemand
## 1       1232.9      550       31498.9 376.0        1         623.0      500
## 2       1232.9      550       31498.9 346.0        1         653.0      500
## 3       1232.9      550       31498.9 254.0        1         745.0      500
## 4       1232.9      600       31498.9 363.0        1         636.0      500
## 5       1232.9      600       31498.9 346.0        1         653.0      500
## 6       1232.9      600       31498.9 361.2        1         638.0      500
## 7       1232.9      600       31498.9 363.0        1         636.1      500
## 8       1232.9      600       31498.9 346.0        1         653.0      500
## 9       1232.9      600       31498.9 401.6        1         597.6      500
## 10      1232.9      595       31498.9 340.0        1         659.0      500
## 11      1232.9      595       31498.9 376.0        1         623.1      500
## 12      1232.9      595       31498.9 320.3        0         679.9      500
## 13      1232.9      600       31498.9 415.0        0         585.2      500
## 14      1232.9      595       31498.9 376.0        0         624.0      500
## 15      1232.9      595       31498.9 350.0        1         649.0      500
## 16      1232.9      600       31498.9 310.0        1         689.0      500
## 17      1232.9      595       31498.9 307.3        1         691.8      500
## 18      1232.9      595       31498.9 307.3        1         691.9      500
## 19      1232.9      595       31498.9 307.3        1         692.1      500
## 20      1232.9      595       31498.9 307.3        1         692.0      500
## 21      1232.9      595       31498.9 307.3        1         691.9      500
## 22      1232.9      595       31498.9 310.0        1         689.2      500
## 23      1232.9      600       31498.9 310.0        1         689.0      500
## 24      1232.9      600       31498.9 350.0        1         649.1      500
##    srOffering srPrice srRegistered supBid supBidQse supBidNontrade supDemand
## 1    4854.444     400     10215.64  869.7         0          130.5      1000
## 2    4854.444     400     10215.64  823.1         0          177.2      1000
## 3    4854.444     400     10215.64  809.4         0          190.9      1000
## 4    4854.444     400     10215.64  759.3         0          241.2      1000
## 5    4854.444     400     10215.64  739.9         0          260.7      1000
## 6    4854.444     400     10215.64  844.5         0          155.9      1000
## 7    4854.444     400     10215.64  839.4         0          161.0      1000
## 8    4854.444     400     10215.64  685.4         0          315.1      1000
## 9    4854.444     400     10215.64  940.1         0           60.1      1000
## 10   4854.444     400     10215.64  872.2         0          127.9      1000
## 11   4854.444     400     10215.64  907.9         0           92.2      1000
## 12   4853.444     400     10215.64  915.2         0           84.9      1000
## 13   4853.444     400     10215.64  873.0         0          127.1      1000
## 14   4853.444     400     10215.64  922.2         0           78.0      1000
## 15   4854.444     400     10215.64  867.8         0          132.7      1000
## 16   4854.444     400     10215.64  893.3         0          107.0      1000
## 17   4854.444     400     10215.64  765.3         0          235.2      1000
## 18   4854.444     400     10215.64  856.3         0          144.1      1000
## 19   4829.444     400     10215.64  524.1         0           33.2      1000
## 20   4854.444     400     10215.64  859.4         0          140.7      1000
## 21   4854.444     400     10215.64  843.6         0          156.6      1000
## 22   4854.444     400     10215.64  991.6         0            8.6      1000
## 23   4854.444     400     10215.64  922.2         0           78.0      1000
## 24   4854.444     400     10215.64  902.6         0           97.5      1000
##    supOffering supPrice supRegistered
## 1     7437.194      350      14174.55
## 2     7437.194      350      14174.55
## 3     7437.194      350      14174.55
## 4     7437.194      350      14174.55
## 5     7437.194      350      14174.55
## 6     7437.194      350      14174.55
## 7     7437.194      350      14174.55
## 8     7437.194      350      14174.55
## 9     7437.194      350      14174.55
## 10    7437.194      350      14174.55
## 11    7437.194      350      14174.55
## 12    7437.194      350      14174.55
## 13    7437.194      350      14174.55
## 14    7437.194      350      14174.55
## 15    7437.194      350      14174.55
## 16    7437.194      350      14174.55
## 17    7437.194      350      14174.55
## 18    7437.194      350      14174.55
## 19    7397.194      350      14174.55
## 20    7437.194      350      14174.55
## 21    7437.194      350      14174.55
## 22    7437.194      350      14174.55
## 23    7437.194      350      14174.55
## 24    7437.194      350      14174.55

選取json中名為的data物件,則dfi即為一個dataframe物件。

dfi <- dfi$data

在資料中分別有日期以及時間兩個變項,而我們想要將兩個變項tranDatetranHour合成為一個日期時間datetime格式的變項。ymd_hm()可以將year/month/day hour:minute排列方式的資料轉換成日期時間格式,有許多不同格式相同功能的函數可以使用。mutate則是新增欄位,等式左邊為新增變數名,等式右邊為新增變數的內容。

dfi <- mutate(.data = dfi,
              datetime = ymd_hm(paste0(tranDate, " ", tranHour)))

dfi$datetime
##  [1] "2021-11-16 00:00:00 UTC" "2021-11-16 01:00:00 UTC"
##  [3] "2021-11-16 02:00:00 UTC" "2021-11-16 03:00:00 UTC"
##  [5] "2021-11-16 04:00:00 UTC" "2021-11-16 05:00:00 UTC"
##  [7] "2021-11-16 06:00:00 UTC" "2021-11-16 07:00:00 UTC"
##  [9] "2021-11-16 08:00:00 UTC" "2021-11-16 09:00:00 UTC"
## [11] "2021-11-16 10:00:00 UTC" "2021-11-16 11:00:00 UTC"
## [13] "2021-11-16 12:00:00 UTC" "2021-11-16 13:00:00 UTC"
## [15] "2021-11-16 14:00:00 UTC" "2021-11-16 15:00:00 UTC"
## [17] "2021-11-16 16:00:00 UTC" "2021-11-16 17:00:00 UTC"
## [19] "2021-11-16 18:00:00 UTC" "2021-11-16 19:00:00 UTC"
## [21] "2021-11-16 20:00:00 UTC" "2021-11-16 21:00:00 UTC"
## [23] "2021-11-16 22:00:00 UTC" "2021-11-16 23:00:00 UTC"

由於資料匡中有許多不必要的變數,因此我們使用select()選取需要的變數,我們先前已經有用var儲存想要的變數,將其條件放入select函數中。

select(.data = dfi, var)
## Warning: Using an external vector in selections was deprecated in tidyselect 1.1.0.
## ℹ Please use `all_of()` or `any_of()` instead.
##   # Was:
##   data %>% select(var)
## 
##   # Now:
##   data %>% select(all_of(var))
## 
## See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
##               datetime srBid srBidQse srPrice supBid supBidQse supPrice
## 1  2021-11-16 00:00:00 376.0        1     400  869.7         0      350
## 2  2021-11-16 01:00:00 346.0        1     400  823.1         0      350
## 3  2021-11-16 02:00:00 254.0        1     400  809.4         0      350
## 4  2021-11-16 03:00:00 363.0        1     400  759.3         0      350
## 5  2021-11-16 04:00:00 346.0        1     400  739.9         0      350
## 6  2021-11-16 05:00:00 361.2        1     400  844.5         0      350
## 7  2021-11-16 06:00:00 363.0        1     400  839.4         0      350
## 8  2021-11-16 07:00:00 346.0        1     400  685.4         0      350
## 9  2021-11-16 08:00:00 401.6        1     400  940.1         0      350
## 10 2021-11-16 09:00:00 340.0        1     400  872.2         0      350
## 11 2021-11-16 10:00:00 376.0        1     400  907.9         0      350
## 12 2021-11-16 11:00:00 320.3        0     400  915.2         0      350
## 13 2021-11-16 12:00:00 415.0        0     400  873.0         0      350
## 14 2021-11-16 13:00:00 376.0        0     400  922.2         0      350
## 15 2021-11-16 14:00:00 350.0        1     400  867.8         0      350
## 16 2021-11-16 15:00:00 310.0        1     400  893.3         0      350
## 17 2021-11-16 16:00:00 307.3        1     400  765.3         0      350
## 18 2021-11-16 17:00:00 307.3        1     400  856.3         0      350
## 19 2021-11-16 18:00:00 307.3        1     400  524.1         0      350
## 20 2021-11-16 19:00:00 307.3        1     400  859.4         0      350
## 21 2021-11-16 20:00:00 307.3        1     400  843.6         0      350
## 22 2021-11-16 21:00:00 310.0        1     400  991.6         0      350
## 23 2021-11-16 22:00:00 310.0        1     400  922.2         0      350
## 24 2021-11-16 23:00:00 350.0        1     400  902.6         0      350

這就是我們需要在每天的資料中抓取的資料,將dfi中的內容併入df中,rbind會根據row方向合併資料框。接下來將使用迴圈完成所有操作。

df <- rbind(df, dfi)

Looping

df <- NULL
for (i in dat){

url <- paste0("https://etp.taipower.com.tw/api/infoboard/settle_value/query?startDate=",
              as.character(i))

dfi <- read_html(url) %>% 
  html_nodes("p") %>% 
  html_text %>%
  fromJSON

dfi <- dfi$data

dfi <- dfi %>% 
  mutate(
    datetime = ymd_hm(paste0(tranDate, " ", tranHour)))

dfi <- dfi %>% select(var)

df <- rbind(df, dfi)

}

最後用nrow觀察資料的筆數,並且用head()查看查詢的結果。

nrow(df)
## [1] 10680
head(df)
##              datetime srBid srBidQse srPrice supBid supBidQse supPrice
## 1 2021-11-16 00:00:00 376.0        1     400  869.7         0      350
## 2 2021-11-16 01:00:00 346.0        1     400  823.1         0      350
## 3 2021-11-16 02:00:00 254.0        1     400  809.4         0      350
## 4 2021-11-16 03:00:00 363.0        1     400  759.3         0      350
## 5 2021-11-16 04:00:00 346.0        1     400  739.9         0      350
## 6 2021-11-16 05:00:00 361.2        1     400  844.5         0      350

Caculation

在取得資料後,我們希望總得標容量以及月平均價格,而平均價格為每小時價格的加權平均數,以每小時得標容量為權重。 我們使用mutate來新增變數,Quant為總容量,計算方式為得標容量(國營)加上得標容量(民營)。由於我們想計算月平均,因此我們需要先將所有資料根據月份分組。format可以更改物件的格式,如下表示將日期時間格式改為年-月格式。%Y為年,而%m為月。str()顯示物件的架構,若函數放入資料框,則回傳每個變數,可以看到最下方三個為剛剛新增的變數。

# sr: 即時備轉, sup: 補充備轉
# Bid: 得標容量(國營)(MW), BidQse: 得標容量(民營)(MW), Price: 結清價格(元 / MW·h)
# Quant = Bid + BidQse

df <- df %>% mutate(month = format(df$datetime, "%Y-%m"), 
                    srQuant = srBid + srBidQse, 
                    supQuant = supBid + supBidQse)

str(df)
## 'data.frame':    10680 obs. of  10 variables:
##  $ datetime : POSIXct, format: "2021-11-16 00:00:00" "2021-11-16 01:00:00" ...
##  $ srBid    : num  376 346 254 363 346 ...
##  $ srBidQse : num  1 1 1 1 1 1 1 1 1 1 ...
##  $ srPrice  : num  400 400 400 400 400 400 400 400 400 400 ...
##  $ supBid   : num  870 823 809 759 740 ...
##  $ supBidQse: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ supPrice : num  350 350 350 350 350 350 350 350 350 350 ...
##  $ month    : chr  "2021-11" "2021-11" "2021-11" "2021-11" ...
##  $ srQuant  : num  377 347 255 364 347 ...
##  $ supQuant : num  870 823 809 759 740 ...

先使用group_by將所有資料根據month分組,接著將分組後的資料傳遞給summarise()函數,summarise會回傳計算後的統計值。weighted.mean()可以計算加權平均數,參數w指定為要使用的權重,na.rm則指定是否略過遺漏值,因為遺漏值無法被計算。w.avg.srPrice為即時備轉月加權平均價格,w.avg.supPrice為補充備轉月加權平均價格。

month_w_avg_price <- df %>% 
  group_by(month) %>% 
  summarise(
    w.avg.srPrice = weighted.mean(srPrice, w = srQuant, na.rm = TRUE),
    w.avg.supPrice = weighted.mean(supPrice, w = supQuant, na.rm = TRUE))

month_w_avg_price
## # A tibble: 16 × 3
##    month   w.avg.srPrice w.avg.supPrice
##    <chr>           <dbl>          <dbl>
##  1 2021-11          400            350 
##  2 2021-12          400.           349.
##  3 2022-01          400.           347.
##  4 2022-02          399.           347.
##  5 2022-03          398.           349.
##  6 2022-04          398.           349.
##  7 2022-05          398.           341.
##  8 2022-06          399.           301.
##  9 2022-07          399.           323.
## 10 2022-08          399.           328.
## 11 2022-09          381.           264.
## 12 2022-10          336.           246.
## 13 2022-11          363.           259.
## 14 2022-12          352.           248.
## 15 2023-01          341.           248.
## 16 2023-02          333.           251.
# mean without weight and advanced method
# df %>% 
#   group_by(month) %>% 
#   summarise( 
#     across(ends_with("Price"), mean, na.rm = TRUE, .names = "avg.{.col}"))

Output

setwd指定我們要儲存資料的資料夾位置。 最後我們需要將整個資料框和計算結果合併成一個excel檔案,並且存於不同的活頁簿,剛好list格式可以方便對應到excel的輸出形式。我們在一個list中建立兩個元素,一個是名為歷史結清價格與交易量的df物件,另一個是名為月均價的month_w_avg_price物件。最後使用write.xlsx將這個list匯出為excel檔案,指定檔案名為”歷史結清價格與交易量.xlsx”。 接下來就可以到資料夾內查看輸出的excel檔案。

setwd("~/Desktop/R/CIER/電力交易平台")

output <- list(歷史結清價格與交易量 = df, 月均價 = month_w_avg_price)

str(output)
## List of 2
##  $ 歷史結清價格與交易量:'data.frame':  10680 obs. of  10 variables:
##   ..$ datetime : POSIXct[1:10680], format: "2021-11-16 00:00:00" "2021-11-16 01:00:00" ...
##   ..$ srBid    : num [1:10680] 376 346 254 363 346 ...
##   ..$ srBidQse : num [1:10680] 1 1 1 1 1 1 1 1 1 1 ...
##   ..$ srPrice  : num [1:10680] 400 400 400 400 400 400 400 400 400 400 ...
##   ..$ supBid   : num [1:10680] 870 823 809 759 740 ...
##   ..$ supBidQse: num [1:10680] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ supPrice : num [1:10680] 350 350 350 350 350 350 350 350 350 350 ...
##   ..$ month    : chr [1:10680] "2021-11" "2021-11" "2021-11" "2021-11" ...
##   ..$ srQuant  : num [1:10680] 377 347 255 364 347 ...
##   ..$ supQuant : num [1:10680] 870 823 809 759 740 ...
##  $ 月均價              : tibble [16 × 3] (S3: tbl_df/tbl/data.frame)
##   ..$ month         : chr [1:16] "2021-11" "2021-12" "2022-01" "2022-02" ...
##   ..$ w.avg.srPrice : num [1:16] 400 400 400 399 398 ...
##   ..$ w.avg.supPrice: num [1:16] 350 349 347 347 349 ...
write.xlsx(output, file = "歷史結清價格與交易量.xlsx")