This vignette introduces the Epw
class which is designed
to read and modify EnergyPlus Weather Files (EPWs).
eplusr contains a helper function download_weather()
which can be used to download EnergyPlus EPW and DDY files from EnergyPlus weather
website.
download_weather()
takes a regular expression to search
weather specifications and gives you a menu to choose files to download
from matched results. Note that the matching is case-insensitive. Files
downloaded will be renamed according to input filename
argument.
download_weather("los angeles", filename = "Los Angeles", dir = tempdir())
#> 3 matched results found. Please select which one to download:
#>
#> ── [1] USA_CA_Los.Angeles.722950_TMY2 ───────────────────
#> * Country: United States of America
#> * State or Province: CA
#> * Location: CA_Los.Angeles
#> * WMO number: 722950
#> * Source type: TMY2
#> * Longitude: -118.4
#> * Latitude: 33.93
#>
#> ── [2] USA_CA_Los.Angeles.Intl.AP.722950_TMY ────────────
#> * Country: United States of America
#> * State or Province: CA
#> * Location: CA_Los.Angeles.Intl.AP
#> * WMO number: 722950
#> * Source type: TMY
#> * Longitude: -118.4
#> * Latitude: 33.93
#>
#> ── [3] USA_CA_Los.Angeles.Intl.AP.722950_TMY3 ───────────
#> * Country: United States of America
#> * State or Province: CA
#> * Location: CA_Los.Angeles.Intl.AP
#> * WMO number: 722950
#> * Source type: TMY3
#> * Longitude: -118.4
#> * Latitude: 33.93
#>
#> 1: USA_CA_Los.Angeles.722950_TMY2
#> 2: USA_CA_Los.Angeles.Intl.AP.722950_TMY
#> 3: USA_CA_Los.Angeles.Intl.AP.722950_TMY3
#> 4: All
#>
#> Selection:
By default, it will download both EPW and DDY files of selected
results. You can change that by modifying the type
argument
to only download either EPW files or DDY files.
Reading an EPW file starts with function read_epw()
,
which parses an EPW file and returns an Epw
object. The
parsing process is basically the same as
EnergyPlus/WeatherManager.cc
in EnergyPlus, with some
simplifications.
An EPW file can be divided into two parts, headers and weather data. The first eight lines of a standard EPW file are normally headers which contains data of location, design conditions, typical/extreme periods, ground temperatures, holidays/daylight savings, data periods and other comments.
Epw
class provides methods to directly extract those
data. For details on the data structure of EPW file, please see “Chapter
2 - Weather Converter Program” in EnergyPlus “Auxiliary Programs”
documentation. An online version can be found here.
path <- path_eplus_weather("23.1", "USA_CA_San.Francisco.Intl.AP.724940_TMY3.epw")
epw <- read_epw(path)
epw
#> ══ EnergyPlus Weather File ═════════════════════════════════════════════════════
#> [Location ]: San Francisco Intl Ap, CA, USA
#> {N 37°37'}, {W 122°24'}, {UTC-08:00}
#> [Elevation]: 2m above see level
#> [Data Src ]: TMY3
#> [WMO Stat ]: 724940
#> [Leap Year]: No
#> [Interval ]: 60 mins
#>
#> ── Data Periods ────────────────────────────────────────────────────────────────
#> Name StartDayOfWeek StartDay EndDay
#> 1: Data Sunday 1/ 1 12/31
#>
#> ────────────────────────────────────────────────────────────────────────────────
Epw
class provides 10 methods to extract and modify EPW
header data, including:
Header | Method |
---|---|
LOCATION |
$location() |
DESIGN CONDITIONS |
$design_condition() |
TYPICAL/EXTREME PERIODS |
$typical_extreme_period() |
GROUND TEMPERATURES |
$ground_temperature() |
HOLIDAYS/DAYLIGHT SAVINGS |
$holiday() |
COMMENTS 1 |
$comment1() |
COMMENTS 2 |
$comment2() |
DATA PERIODS |
$num_period() , $interval()
& $period()
|
$data()
can be used to extract the core weather data.
Usually, EPW file downloaded from EnergyPlus website contains TMY
weather data. As years of weather data is not consecutive, it may be
more convenient to align the year values to be consecutive, which will
makes it possible to direct analyze and plot weather data. The
start_year
argument in $data()
method can help
to achieve this. However, randomly setting the year
may
result in a date time series that does not have the same start day of
week as specified in the DATA PERIODS
header. eplusr
provides a simple solution for this. By setting year
to
NULL
and align_wday
to TRUE
,
eplusr will calculate a year value (from current year backwards) for
each data period that compliance with the start day of week
restriction.
str(head(epw$data()))
#> Classes 'data.table' and 'data.frame': 6 obs. of 36 variables:
#> $ datetime : POSIXct, format: "2023-01-01 01:00:00" "2023-01-01 02:00:00" ...
#> $ year : int 1999 1999 1999 1999 1999 1999
#> $ month : int 1 1 1 1 1 1
#> $ day : int 1 1 1 1 1 1
#> $ hour : int 1 2 3 4 5 6
#> $ minute : int 0 0 0 0 0 0
#> $ data_source : chr "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" "?9?9?9?9E0?9?9?9?9?9?9?9?9?9?9?9?9?9?9?9*9*9?9?9?9" ...
#> $ dry_bulb_temperature : num 7.2 7.2 6.7 6.1 4.4 4.4
#> $ dew_point_temperature : num 5.6 5.6 5 5 3.9 3.9
#> $ relative_humidity : num 90 90 89 93 97 97
#> $ atmospheric_pressure : num 102200 102100 102200 102200 102200 ...
#> $ extraterrestrial_horizontal_radiation : num 0 0 0 0 0 0
#> $ extraterrestrial_direct_normal_radiation : num 0 0 0 0 0 0
#> $ horizontal_infrared_radiation_intensity_from_sky: num 290 296 291 276 280 280
#> $ global_horizontal_radiation : num 0 0 0 0 0 0
#> $ direct_normal_radiation : num 0 0 0 0 0 0
#> $ diffuse_horizontal_radiation : num 0 0 0 0 0 0
#> $ global_horizontal_illuminance : num 0 0 0 0 0 0
#> $ direct_normal_illuminance : num 0 0 0 0 0 0
#> $ diffuse_horizontal_illuminance : num 0 0 0 0 0 0
#> $ zenith_luminance : num 0 0 0 0 0 0
#> $ wind_direction : num 0 170 210 200 260 180
#> $ wind_speed : num 0 2.1 2.1 1.5 3.1 2.1
#> $ total_sky_cover : int 2 4 3 0 3 3
#> $ opaque_sky_cover : int 2 4 3 0 3 3
#> $ visibility : num 16 16 16 16 16 16
#> $ ceiling_height : num 77777 77777 77777 77777 77777 ...
#> $ present_weather_observation : int 9 9 9 9 9 9
#> $ present_weather_codes : chr "999999999" "999999999" "999999999" "999999999" ...
#> $ precipitable_water : num 129 120 120 120 120 120
#> $ aerosol_optical_depth : num 0.108 0.108 0.108 0.108 0.108 0.108
#> $ snow_depth : num 0 0 0 0 0 0
#> $ days_since_last_snow : int 88 88 88 88 88 88
#> $ albedo : num 0.16 0.16 0.16 0.16 0.16 0.16
#> $ liquid_precip_depth : num 0 0 0 0 0 0
#> $ liquid_precip_rate : num 1 1 1 1 1 1
#> - attr(*, ".internal.selfref")=<externalptr>
$abnormal_data()
returns abnormal data of specific data
period. Basically, there are 2 types of abnormal data in
Epw
, i.e. missing values and out-of-range values.
Sometimes, it may be useful to extract and inspect those data especially
when inserting measured weather data. $abnormal_data()
does
this.
In the returned data.table
, a column named
line
is created indicating the line numbers where abnormal
data occur in the actual EPW file.
print(epw$abnormal_data(cols = "albedo", keep_all = FALSE))
#> line datetime year month day hour minute albedo
#> <int> <POSc> <int> <int> <int> <int> <int> <num>
#> 1: 753 1977-02-01 01:00:00 1977 2 1 1 0 999
#> 2: 754 1977-02-01 02:00:00 1977 2 1 2 0 999
#> 3: 755 1977-02-01 03:00:00 1977 2 1 3 0 999
#> 4: 756 1977-02-01 04:00:00 1977 2 1 4 0 999
#> 5: 757 1977-02-01 05:00:00 1977 2 1 5 0 999
#> ---
#> 2156: 5836 1985-08-31 20:00:00 1985 8 31 20 0 999
#> 2157: 5837 1985-08-31 21:00:00 1985 8 31 21 0 999
#> 2158: 5838 1985-08-31 22:00:00 1985 8 31 22 0 999
#> 2159: 5839 1985-08-31 23:00:00 1985 8 31 23 0 999
#> 2160: 5840 1985-09-01 00:00:00 1985 8 31 24 0 999
You can use $make_na()
to turn all abnormal data into
NAs:
epw$make_na(missing = TRUE, out_of_range = TRUE)
print(epw$abnormal_data(cols = "albedo", keep_all = FALSE))
#> line datetime year month day hour minute albedo
#> <int> <POSc> <int> <int> <int> <int> <int> <num>
#> 1: 753 1977-02-01 01:00:00 1977 2 1 1 0 NA
#> 2: 754 1977-02-01 02:00:00 1977 2 1 2 0 NA
#> 3: 755 1977-02-01 03:00:00 1977 2 1 3 0 NA
#> 4: 756 1977-02-01 04:00:00 1977 2 1 4 0 NA
#> 5: 757 1977-02-01 05:00:00 1977 2 1 5 0 NA
#> ---
#> 2156: 5836 1985-08-31 20:00:00 1985 8 31 20 0 NA
#> 2157: 5837 1985-08-31 21:00:00 1985 8 31 21 0 NA
#> 2158: 5838 1985-08-31 22:00:00 1985 8 31 22 0 NA
#> 2159: 5839 1985-08-31 23:00:00 1985 8 31 23 0 NA
#> 2160: 5840 1985-09-01 00:00:00 1985 8 31 24 0 NA
Or use $fill_abnormal()
to fill NAs back to missing
codes:
epw$fill_abnormal(missing = TRUE, out_of_range = TRUE)
print(epw$abnormal_data(cols = "albedo", keep_all = FALSE))
#> line datetime year month day hour minute albedo
#> <int> <POSc> <int> <int> <int> <int> <int> <num>
#> 1: 753 1977-02-01 01:00:00 1977 2 1 1 0 999
#> 2: 754 1977-02-01 02:00:00 1977 2 1 2 0 999
#> 3: 755 1977-02-01 03:00:00 1977 2 1 3 0 999
#> 4: 756 1977-02-01 04:00:00 1977 2 1 4 0 999
#> 5: 757 1977-02-01 05:00:00 1977 2 1 5 0 999
#> ---
#> 2156: 5836 1985-08-31 20:00:00 1985 8 31 20 0 999
#> 2157: 5837 1985-08-31 21:00:00 1985 8 31 21 0 999
#> 2158: 5838 1985-08-31 22:00:00 1985 8 31 22 0 999
#> 2159: 5839 1985-08-31 23:00:00 1985 8 31 23 0 999
#> 2160: 5840 1985-09-01 00:00:00 1985 8 31 24 0 999
Epw
class provides $add()
,
$set()
and $del()
methods to add, update and
delete a new data period, respectively.
Below we extract weather data with automatically calculated year values, and replace the existing data and turn it into an AMY weather data.
d <- epw$data()
print(d[, .(datetime)])
#> datetime
#> <POSc>
#> 1: 2023-01-01 01:00:00
#> 2: 2023-01-01 02:00:00
#> 3: 2023-01-01 03:00:00
#> 4: 2023-01-01 04:00:00
#> 5: 2023-01-01 05:00:00
#> ---
#> 8756: 2023-12-31 20:00:00
#> 8757: 2023-12-31 21:00:00
#> 8758: 2023-12-31 22:00:00
#> 8759: 2023-12-31 23:00:00
#> 8760: 2024-01-01 00:00:00
epw$set(d, realyear = TRUE)
#> ── Info ────────────────────────────────────────────────────────────────────────
#> Data period #1 has been replaced with input data.
#>
#> Name StartDayOfWeek StartDay EndDay
#> 1: Data Sunday 2023/ 1/ 1 2023/12/31
#> ────────────────────────────────────────────────────────────────────────────────
Epw
class supports multiple data periods in a single EPW
file:
d <- epw$data(start_year = 2014, align_wday = FALSE)
#> Warning: Invalid 'start_year' found for Data period #1 'Data' starting from
#> 2023/ 1/ 1 to 2023/12/31. The original starting date falls in a leap year,
#> however input 'start_year' is not a leap year. Invalid date time may occur.
#> Warning: Data period #1 'Data' seems like a real-year data starting from 2023/
#> 1/ 1 to 2023/12/31. The starting date will be overwriten as 2014/ 1/ 1.
epw$add(d, after = 0L, realyear = TRUE)
#> ── Info ────────────────────────────────────────────────────────────────────────
#> New data period has been added successfully:
#>
#> Name StartDayOfWeek StartDay EndDay
#> 1: Data1 Wednesday 2014/ 1/ 1 2014/12/31
#> ────────────────────────────────────────────────────────────────────────────────
epw$period()
#> index name start_day_of_week start_day end_day
#> <int> <char> <char> <EpwDate> <EpwDate>
#> 1: 1 Data1 Wednesday 2014/ 1/ 1 2014/12/31
#> 2: 2 Data Sunday 2023/ 1/ 1 2023/12/31