-
Notifications
You must be signed in to change notification settings - Fork 0
Hurricane Data
This wiki page walks through how to create a census block group level by date table with an indicator for the highest intensity of any tropical cyclone that the geography encountered that day using the last ten years' worth of NOAA's global hurricane tracks data in Google Cloud's BigQuery table bigquery-public-data.noaa_hurricanes.hurricanes
.
Creating this table will enable you to analyze customer behavior pre/post major storm activity.
The National Oceanic and Atmospheric Administration (NOAA) is an American scientific agency within the United States Department of Commerce that focuses on the conditions of the oceans, major waterways, and the atmosphere. NOAA warns of dangerous weather, charts seas, guides the use and protection of ocean and coastal resources and conducts research to provide the understanding and improve stewardship of the environment.
Note: some of this descriptive content is copy/paste from the NOAA/other sources and consolidated here in an effort to create a quick learning guide.
Saffir–Simpson Hurricane Wind Scale (SSHWS)
The SSHWS is a 1 to 5 rating based on a hurricane's sustained wind speed. This scale estimates potential property damage. Hurricanes reaching Category 3 and higher are considered major hurricanes because of their potential for significant loss of life and damage. Category 1 and 2 storms are still dangerous, however, and require preventative measures.
A tropical cyclone is a rotating low-pressure weather system that has organized thunderstorms but no fronts (a boundary separating two air masses of different densities). Tropical cyclones with maximum one-minute sustained surface winds of less than 39 miles per hour (mph) are called tropical depressions. Those with maximum one-minute sustained winds of 39 mph or higher are called tropical storms. When a storm's maximum one-minute sustained winds reach 74 mph, it is called a hurricane.
-
Scales:
Category
Damage
m/s
knots (kn)
mph
km/h
Five
Catastrophic
≥ 70 m/s
≥ 137 kn
≥ 157 mph
≥ 252 km/h
Four
Catastrophic
58–70 m/s
113–136 kn
130–156 mph
209–251 km/h
Three
Devastating
50–58 m/s
96–112 kn
111–129 mph
178–208 km/h
Two
Extensive
43–49 m/s
83–95 kn
96–110 mph
154–177 km/h
One
Some
33–42 m/s
64–82 kn
74–95 mph
119–153 km/h
Tropical Storm
18–32 m/s
34–63 kn
39–73 mph
63–118 km/h
Tropical Depression
≤ 17 m/s
≤ 33 kn
≤ 38 mph
≤ 62 km/h
-
Category One
Very dangerous winds will produce some damage: Well-constructed frame homes could have damage to roof, shingles, vinyl siding and gutters. Large branches of trees will snap and shallowly rooted trees may be toppled. Extensive damage to power lines and poles likely will result in power outages that could last a few to several days.
-
Category Two
Extremely dangerous winds will cause extensive damage: Well-constructed frame homes could sustain major roof and siding damage. Many shallowly rooted trees will be snapped or uprooted and block numerous roads. Near-total power loss is expected with outages that could last from several days to weeks.
-
Category Three
Devastating damage will occur: Well-built framed homes may incur major damage or removal of roof decking and gable ends. Many trees will be snapped or uprooted, blocking numerous roads. Electricity and water will be unavailable for several days to weeks after the storm passes.
-
Category Four
Catastrophic damage will occur: Well-built framed homes can sustain severe damage with loss of most of the roof structure and/or some exterior walls. Most trees will be snapped or uprooted and power poles downed. Fallen trees and power poles will isolate residential areas. Power outages will last weeks to possibly months. Most of the area will be uninhabitable for weeks or months.
-
Category Five
Catastrophic damage will occur: A high percentage of framed homes will be destroyed, with total roof failure and wall collapse. Fallen trees and power poles will isolate residential areas. Power outages will last for weeks to possibly months. Most of the area will be uninhabitable for weeks or months.
-
Census block group table that lists the highest storm wind by date (rolling ten years).
GEOID_BLK_GRP
STORM_DT
SID
NAME
SSHS
120570065023
2017-09-11
2017242N16333
IRMA
CAT1
482013140022
2017-08-28
2017228N14314
HARVEY
Tropical Storm
120050020001
2018-10-10
2018280N18273
MICHAEL
CAT5
721130713003
2017-09-20
2017260N12310
MARIA
CAT4
120710403122
2017-09-10
2017242N16333
IRMA
CAT3
-
GEOID_BLK_GRP
: Unique identifier for each census block group. A concatenation of the current state FIPS code, county FIPS code, census tract code, and block group code (first character of block code). -
STORM_DT
: Date the tropical cyclone hit the census block group. -
SID
: Storm ID of the storm with the greatest winds that day. -
NAME
: Name of the storm with the greatest winds that day. -
SSHS
: Highest wind classification for that day. Tropical storm or Saffir-Simpson hurricane wind scale category 1-5.
-
-
Census block group level table with flags that indicate whether it was struck by a tropical cyclone in the past 90 days.
This view aggregates the data from the above table with 90 day indicator columns.
CREATE OR REPLACE VIEW `blkgrp_hurr_r3` AS SELECT A.geo_id GEOID_BLK_GRP , MAX(CASE WHEN B.GEOID_BLK_GRP IS NOT NULL THEN 1 ELSE 0 END) HURR_90DAY_IND , MAX(CASE WHEN B.SSHS = 'Tropical Storm' THEN 1 ELSE 0 END) HURR_90DAY_TS , MAX(CASE WHEN B.SSHS = 'CAT1' THEN 1 ELSE 0 END) HURR_90DAY_F1 , MAX(CASE WHEN B.SSHS = 'CAT2' THEN 1 ELSE 0 END) HURR_90DAY_F2 , MAX(CASE WHEN B.SSHS = 'CAT3' THEN 1 ELSE 0 END) HURR_90DAY_F3 , MAX(CASE WHEN B.SSHS = 'CAT4' THEN 1 ELSE 0 END) HURR_90DAY_F4 , MAX(CASE WHEN B.SSHS = 'CAT5' THEN 1 ELSE 0 END) HURR_90DAY_F5 FROM `bigquery-public-data.geo_census_blockgroups.blockgroups_*` A LEFT JOIN `blkgrp_hurr` B ON A.geo_id = B.GEOID_BLK_GRP AND STORM_DT BETWEEN DATE_SUB(CURRENT_DATE("America/New_York"), INTERVAL 90 DAY) AND CURRENT_DATE("America/New_York") GROUP BY 1;
GEOID_BLK_GRP
HURR_90DAY_IND
HURR_90DAY_TS
HURR_90DAY_F1
HURR_90DAY_F2
HURR_90DAY_F3
HURR_90DAY_F4
HURR_90DAY_F5
212219702003
0
0
0
0
0
0
0
110010023021
1
1
0
0
0
0
0
220039505003
1
0
1
0
0
1
0
This source data contains the most complete global set of historical tropical cyclones available. The NOAA's IBTrACS provides this tropical cyclone best track data in a centralized location to aid the understanding of the distribution, frequency, and intensity of tropical cyclones worldwide:
The historical positions and intensities along the tracks of global tropical cyclones (TC) are provided by NOAA’s International Best Track Archive for Climate Stewardship (IBTrACS). Tropical Cyclones are known as hurricanes in the north Atlantic and northeast Pacific ocean basins, typhoons in the northwest Pacific ocean basin, cyclones in the north and south Indian Ocean basins, and tropical cyclones in the southwest Pacific ocean basin. IBTrACS collects data about TCs reported by international monitoring centers who have a responsibility to forecast and report on TCs (and also includes some important historical datasets). Presently, IBTrACS includes data from 9 different countries. Historically, the data describing these systems has included best estimates of their track and intensity (hence the term, best track).
-
Sample Data:
SID
NAME
ISO_TIME
DIST2LAND
USA_RMW
USA_WIND
LONGITUDE
LATITUDE
... 2014284N10231
ANA
2014-10-18 12:00:00 UTC
214
20
70
-157.7
18.2
2019246N15225
AKONI
2019-09-04 12:00:00 UTC
1714
60
25
-140.0
13.5
2018218N18134
YAGI
2018-08-09 21:00:00 UTC
967
80
37
132.583
22.5228
2015068S12151
NATHAN
2015-03-11 00:00:00 UTC
217
40
45
146.8
-13.75
2016041S14170
WINSTON
2016-02-21 12:00:00 UTC
425
12
115
173.2
-17.6
-
SID
: Storm Identifier. -
NAME
: Name provided by the agency. IBTrACS ignores most names that include digits or abbreviations. -
ISO_TIME
: ISO Time provided in Universal Time Coordinates (UTC). Format is YYYY-MM-DD HH:mm:ss Most points are provided at 6 hour intervals. Some agencies provided 3 hour points (e.g., New Delhi) or times at important observations (e.g., landfall times in the North Atlantic, etc.). -
DIST2LAND
: Distance to land from the current position. The land dataset includes all continents and any islands larger than XX. The distance is the nearest at the present time in any direction. -
USA_RMW
: radius of max winds, 0 - 999 n mi. NOT BEST TRACKED (not reanalyzed) -
USA_WIND
: Maximum sustained wind speed in knots: 0 - 300 kts. -
LONGITUDE
: -
LATITUDE
: -
etc..
: 12 columns that are the wind radii maximum extent in the direction of specific quadrants with a specific knot indicator. ExampleUSA_R34_NE
= 34 kt wind radii maximum extent in northeastern quadrant.
-
The simplified explanation of this process is taking each tropical cyclone's data point and tagging all census block group centroids that are within 'x' miles of the data point, 'x' defined by the distance the wind intensity can reach.
-
t01: create base data
In this step, we grab the past ten years' worth of data that we need as well as calculate a few fields /
LEAD()
several columns by the storm ID ordered by the timestamp. All of the lead attributes are the subsequent data point in time for the storm. This will allow us to later see if the distance between the two data points is too great to where we'll need to interpolate additional data points.SELECT SID, NAME , EXTRACT(DATE FROM iso_time) STORM_DT , dist2land - usa_rmw LAND_AFFECT , ISO_TIME , USA_WIND, usa_rmw , LEAD(USA_WIND) OVER(PARTITION BY SID ORDER BY iso_time) USA_WIND2 , LEAD(usa_rmw) OVER(PARTITION BY SID ORDER BY iso_time) usa_rmw2 , LONGITUDE, LATITUDE , LEAD(LONGITUDE) OVER(PARTITION BY SID ORDER BY iso_time) LONG2 , LEAD(LATITUDE) OVER(PARTITION BY SID ORDER BY iso_time) LAT2 , usa_r34_ne, usa_r34_nw, usa_r34_se, usa_r34_sw , usa_r50_ne, usa_r50_nw, usa_r50_se, usa_r50_sw , usa_r64_ne, usa_r64_nw, usa_r64_se, usa_r64_sw , LEAD(usa_r34_ne) OVER(PARTITION BY SID ORDER BY iso_time) usa_r34_ne2 , LEAD(usa_r34_nw) OVER(PARTITION BY SID ORDER BY iso_time) usa_r34_nw2 , LEAD(usa_r34_se) OVER(PARTITION BY SID ORDER BY iso_time) usa_r34_se2 , LEAD(usa_r34_sw) OVER(PARTITION BY SID ORDER BY iso_time) usa_r34_sw2 , LEAD(usa_r50_ne) OVER(PARTITION BY SID ORDER BY iso_time) usa_r50_ne2 , LEAD(usa_r50_nw) OVER(PARTITION BY SID ORDER BY iso_time) usa_r50_nw2 , LEAD(usa_r50_se) OVER(PARTITION BY SID ORDER BY iso_time) usa_r50_se2 , LEAD(usa_r50_sw) OVER(PARTITION BY SID ORDER BY iso_time) usa_r50_sw2 , LEAD(usa_r64_ne) OVER(PARTITION BY SID ORDER BY iso_time) usa_r64_ne2 , LEAD(usa_r64_nw) OVER(PARTITION BY SID ORDER BY iso_time) usa_r64_nw2 , LEAD(usa_r64_se) OVER(PARTITION BY SID ORDER BY iso_time) usa_r64_se2 , LEAD(usa_r64_sw) OVER(PARTITION BY SID ORDER BY iso_time) usa_r64_sw2 , ( SELECT MIN(x) FROM UNNEST( [ usa_rmw , usa_r34_ne, usa_r34_nw, usa_r34_se, usa_r34_sw , usa_r50_ne, usa_r50_nw, usa_r50_se, usa_r50_sw , usa_r64_ne, usa_r64_nw, usa_r64_se, usa_r64_sw ] ) x ) MIN_DIST -- Minimum Distance FROM `bigquery-public-data.noaa_hurricanes.hurricanes` WHERE CAST(SEASON AS INT64) >= ( EXTRACT(YEAR FROM CURRENT_DATE) - 10 ) AND USA_WIND IS NOT NULL LIMIT 5;
-
t02: generate additional coordinates if needed
In this step, we run all of our coordinates through our
udf_intrpl_latlon()
function which generates a linestring between our current point and the next point if the distance between them is shorter than the minimum wind affect difference. This is an important step to ensure that we're not overlooking tagging census block groups that have been impacted by a tropical storm simply because the NOAA data had gaps between coordinates. So we use this function to generate coordinates between them by using the forward azimuth and assuming the storm's path between the two coordinates is a straight line.Then we remove all final points that aren't close enough to affect land.
SELECT A.* , ( ST_DISTANCE(ST_GEOGPOINT( LONGITUDE, LATITUDE) , ST_GEOGPOINT(LONG2, LAT2 ))/ 1609.344) DIST , INTRPL , OFFSET FROM t01 A , UNNEST( `udf.udf_intrpl_latlon` (LATITUDE, LONGITUDE, LAT2, LONG2,MIN_DIST) ) INTRPL WITH OFFSET WHERE LAND_AFFECT <= 0;
-
t03: interpolate wind values for generated coordinates
For every coordinate that we generated in
t02
, we interpolate the wind values by slowly increasing/decreasing between the values from the original coordinates that we used to generate the new coordinates.For example, if we created
coor B
midway betweencoor A
andcoor C
, then for wind variableusa_r34_ne
, we take the midway between A and C's value forusa_r34_ne
.SELECT SID, NAME , STORM_DT , ISO_TIME , INTRPL.LONG , INTRPL.LAT , ST_GEOGPOINT( INTRPL.LONG, INTRPL.LAT) point , USA_WIND + COALESCE(( ((USA_WIND2-USA_WIND)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) USA_WIND , usa_r34_ne + COALESCE(( ((usa_r34_ne2-usa_r34_ne)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r34_ne , usa_r34_nw + COALESCE(( ((usa_r34_nw2-usa_r34_nw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r34_nw , usa_r34_se + COALESCE(( ((usa_r34_se2-usa_r34_se)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r34_se , usa_r34_sw + COALESCE(( ((usa_r34_sw2-usa_r34_sw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r34_sw , usa_r50_ne + COALESCE(( ((usa_r50_ne2-usa_r50_ne)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r50_ne , usa_r50_nw + COALESCE(( ((usa_r50_nw2-usa_r50_nw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r50_nw , usa_r50_se + COALESCE(( ((usa_r50_se2-usa_r50_se)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r50_se , usa_r50_sw + COALESCE(( ((usa_r50_sw2-usa_r50_sw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r50_sw , usa_r64_ne + COALESCE(( ((usa_r64_ne2-usa_r64_ne)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r64_ne , usa_r64_nw + COALESCE(( ((usa_r64_nw2-usa_r64_nw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r64_nw , usa_r64_se + COALESCE(( ((usa_r64_se2-usa_r64_se)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r64_se , usa_r64_sw + COALESCE(( ((usa_r64_sw2-usa_r64_sw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_r64_sw , usa_rmw + COALESCE(( ((usa_rmw2-usa_rmw)/(1 + floor(DIST/MIN_DIST))) * OFFSET),0) usa_rmw FROM t02 A;
-
t04: Create geog points for every U.S. Census Block Group's centroid.
SELECT A.GEO_ID , ST_GEOGPOINT( internal_point_lon, internal_point_lat) point , internal_point_lon , internal_point_lat FROM `bigquery-public-data.geo_census_blockgroups.blockgroups_*` A;
-
t05: crossjoin all U.S. Census Block Centroids with all of our hurricane coordinates
In this step, we calculate the distance between each point as well as the bearing at which the hurricane is headed.
SELECT A.* , B.* , (ST_DISTANCE(A.point, B.point) / 1609.344) DIST_MI , `udf.udf_bearing` (A.LAT, A.LONG, B.internal_point_lat, B.internal_point_lon) BEARING FROM t03 A , t04 B ;
-
t06: Calculate the maximum wind speed that affected each census block
Using the bearing of the hurricane, we check all wind columns that are in that direction and apply that wind affect as affecting that census block group if the distance of the wind affect is within range of the block group.
For example, if a hurricane has a bearing of 78 degrees, then the top wind speed from the northeast direction columns is applied.
SELECT GEO_ID GEOID_BLK_GRP , SID, NAME , STORM_DT , MAX( CASE WHEN DIST_MI <= ( SELECT MAX(x) FROM UNNEST( [ CASE WHEN (BEARING BETWEEN 0 AND 90 OR BEARING = 360) THEN (SELECT MAX(y) FROM UNNEST([usa_r34_ne,usa_r50_ne , CASE WHEN USA_WIND BETWEEN 34 AND 63.9999 AND COALESCE(usa_r34_ne,usa_r50_ne,usa_r64_ne) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 90 AND 180 THEN (SELECT MAX(y) FROM UNNEST([usa_r34_se,usa_r50_se , CASE WHEN USA_WIND BETWEEN 34 AND 63.9999 AND COALESCE(usa_r34_se,usa_r50_se,usa_r64_se) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 180 AND 270 THEN (SELECT MAX(y) FROM UNNEST([usa_r34_sw,usa_r50_sw , CASE WHEN USA_WIND BETWEEN 34 AND 63.9999 AND COALESCE(usa_r34_sw,usa_r50_sw,usa_r64_sw) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN (BEARING BETWEEN 270 AND 360 OR BEARING = 0) THEN (SELECT MAX(y) FROM UNNEST([usa_r34_nw,usa_r50_nw , CASE WHEN USA_WIND BETWEEN 34 AND 63.9999 AND COALESCE(usa_r34_nw,usa_r50_nw,usa_r64_nw) IS NOT NULL THEN usa_rmw END]) y) END ]) x) THEN 1 ELSE 0 END) HURR_TS , MAX( CASE WHEN DIST_MI <= ( SELECT MAX(x) FROM UNNEST( [ CASE WHEN (BEARING BETWEEN 0 AND 90 OR BEARING = 360) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 THEN usa_r64_ne END , CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 AND COALESCE(usa_r34_ne,usa_r50_ne,usa_r64_ne) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 90 AND 180 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 THEN usa_r64_se END , CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 AND COALESCE(usa_r34_se,usa_r50_se,usa_r64_se) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 180 AND 270 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 THEN usa_r64_sw END , CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 AND COALESCE(usa_r34_sw,usa_r50_sw,usa_r64_sw) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN (BEARING BETWEEN 270 AND 360 OR BEARING = 0) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 THEN usa_r64_nw END , CASE WHEN USA_WIND BETWEEN 64 AND 82.9999 AND COALESCE(usa_r34_nw,usa_r50_nw,usa_r64_nw) IS NOT NULL THEN usa_rmw END]) y) END ]) x) THEN 1 ELSE 0 END) HURR_F1 , MAX( CASE WHEN DIST_MI <= ( SELECT MAX(x) FROM UNNEST( [ CASE WHEN (BEARING BETWEEN 0 AND 90 OR BEARING = 360) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 THEN usa_r64_ne END , CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 AND COALESCE(usa_r34_ne,usa_r50_ne,usa_r64_ne) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 90 AND 180 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 THEN usa_r64_se END , CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 AND COALESCE(usa_r34_se,usa_r50_se,usa_r64_se) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 180 AND 270 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 THEN usa_r64_sw END , CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 AND COALESCE(usa_r34_sw,usa_r50_sw,usa_r64_sw) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN (BEARING BETWEEN 270 AND 360 OR BEARING = 0) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 THEN usa_r64_nw END , CASE WHEN USA_WIND BETWEEN 83 AND 95.9999 AND COALESCE(usa_r34_nw,usa_r50_nw,usa_r64_nw) IS NOT NULL THEN usa_rmw END]) y) END ]) x) THEN 1 ELSE 0 END) HURR_F2 , MAX( CASE WHEN DIST_MI <= ( SELECT MAX(x) FROM UNNEST( [ CASE WHEN (BEARING BETWEEN 0 AND 90 OR BEARING = 360) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 96 AND 112.999 THEN usa_r64_ne END , CASE WHEN USA_WIND BETWEEN 96 AND 112.999 AND COALESCE(usa_r34_ne,usa_r50_ne,usa_r64_ne) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 90 AND 180 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 96 AND 112.999 THEN usa_r64_se END , CASE WHEN USA_WIND BETWEEN 96 AND 112.999 AND COALESCE(usa_r34_se,usa_r50_se,usa_r64_se) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 180 AND 270 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 96 AND 112.999 THEN usa_r64_sw END , CASE WHEN USA_WIND BETWEEN 96 AND 112.999 AND COALESCE(usa_r34_sw,usa_r50_sw,usa_r64_sw) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN (BEARING BETWEEN 270 AND 360 OR BEARING = 0) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 96 AND 112.999 THEN usa_r64_nw END , CASE WHEN USA_WIND BETWEEN 96 AND 112.999 AND COALESCE(usa_r34_nw,usa_r50_nw,usa_r64_nw) IS NOT NULL THEN usa_rmw END]) y) END ]) x) THEN 1 ELSE 0 END) HURR_F3 , MAX( CASE WHEN DIST_MI <= ( SELECT MAX(x) FROM UNNEST( [ CASE WHEN (BEARING BETWEEN 0 AND 90 OR BEARING = 360) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 113 AND 136.999 THEN usa_r64_ne END , CASE WHEN USA_WIND BETWEEN 113 AND 136.999 AND COALESCE(usa_r34_ne,usa_r50_ne,usa_r64_ne) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 90 AND 180 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 113 AND 136.999 THEN usa_r64_se END , CASE WHEN USA_WIND BETWEEN 113 AND 136.999 AND COALESCE(usa_r34_se,usa_r50_se,usa_r64_se) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 180 AND 270 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 113 AND 136.999 THEN usa_r64_sw END , CASE WHEN USA_WIND BETWEEN 113 AND 136.999 AND COALESCE(usa_r34_sw,usa_r50_sw,usa_r64_sw) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN (BEARING BETWEEN 270 AND 360 OR BEARING = 0) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND BETWEEN 113 AND 136.999 THEN usa_r64_nw END , CASE WHEN USA_WIND BETWEEN 113 AND 136.999 AND COALESCE(usa_r34_nw,usa_r50_nw,usa_r64_nw) IS NOT NULL THEN usa_rmw END]) y) END ]) x) THEN 1 ELSE 0 END) HURR_F4 , MAX( CASE WHEN DIST_MI <= ( SELECT MAX(x) FROM UNNEST( [ CASE WHEN (BEARING BETWEEN 0 AND 90 OR BEARING = 360) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND >= 137 THEN usa_r64_ne END , CASE WHEN USA_WIND >= 137 AND COALESCE(usa_r34_ne,usa_r50_ne,usa_r64_ne) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 90 AND 180 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND >= 137 THEN usa_r64_se END , CASE WHEN USA_WIND >= 137 AND COALESCE(usa_r34_se,usa_r50_se,usa_r64_se) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN BEARING BETWEEN 180 AND 270 THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND >= 137 THEN usa_r64_sw END , CASE WHEN USA_WIND >= 137 AND COALESCE(usa_r34_sw,usa_r50_sw,usa_r64_sw) IS NOT NULL THEN usa_rmw END]) y) END , CASE WHEN (BEARING BETWEEN 270 AND 360 OR BEARING = 0) THEN (SELECT MAX(y) FROM UNNEST([ CASE WHEN USA_WIND >= 137 THEN usa_r64_nw END , CASE WHEN USA_WIND >= 137 AND COALESCE(usa_r34_nw,usa_r50_nw,usa_r64_nw) IS NOT NULL THEN usa_rmw END]) y) END ]) x) THEN 1 ELSE 0 END) HURR_F5 FROM t05 GROUP BY 1, 2, 3, 4 HAVING (HURR_TS + HURR_F1 + HURR_F2 + HURR_F3 + HURR_F4 + HURR_F5) > 0;
-
hurricanes: aggregate data up to the census block group by date level
We create the final table in this step assigning the Saffir-Simpson hurricane wind scale categories based on the top wind speeds that hit each census block group.
SELECT GEOID_BLK_GRP , STORM_DT , ARRAY_AGG( ( SELECT AS STRUCT SID, NAME , CASE WHEN HURR_F5 = 1 THEN 'CAT5' WHEN HURR_F4 = 1 THEN 'CAT4' WHEN HURR_F3 = 1 THEN 'CAT3' WHEN HURR_F2 = 1 THEN 'CAT2' WHEN HURR_F1 = 1 THEN 'CAT1' WHEN HURR_TS = 1 THEN 'Tropical Storm' END SSHS ) ORDER BY HURR_F5 DESC , HURR_F4 DESC , HURR_F3 DESC , HURR_F2 DESC , HURR_F1 DESC , HURR_TS DESC , SID LIMIT 1 )[SAFE_OFFSET(0)].* FROM t06 GROUP BY 1, 2;