如何使用 BigQuery 获取任何城市的历史天气?

12
4个回答

14

更新于2019年:为了方便起见

SELECT * 
FROM `fh-bigquery.weather_gsod.all`
WHERE name='SAN FRANCISCO INTERNATIONAL A'
ORDER BY date DESC

每日更新 - 如若未更新,请在此处报告

例如,要获取自1980年以来旧金山站点最热的日子:

SELECT name, state, ARRAY_AGG(STRUCT(date,temp) ORDER BY temp DESC LIMIT 5) top_hot, MAX(date) active_until
FROM `fh-bigquery.weather_gsod.all` 
WHERE name LIKE 'SAN FRANC%'
AND date > '1980-01-01'
GROUP BY 1,2
ORDER BY active_until DESC

enter image description here

请注意,由于使用了聚类表,此查询仅处理了28MB。

同样地,但不是使用车站名称,而是使用位置和一个按位置聚类的表:

WITH city AS (SELECT ST_GEOGPOINT(-122.465, 37.807))

SELECT name, state, ARRAY_AGG(STRUCT(date,temp) ORDER BY temp DESC LIMIT 5) top_hot, MAX(date) station_until
FROM `fh-bigquery.weather_gsod.all_geoclustered`  
WHERE EXTRACT(YEAR FROM date) > 1980
AND ST_DISTANCE(point_gis, (SELECT * FROM city)) < 40000
GROUP BY name, state
HAVING EXTRACT(YEAR FROM station_until)>2018
ORDER BY ST_DISTANCE(ANY_VALUE(point_gis), (SELECT * FROM city)) 
LIMIT 5

这里输入图片描述


2017年更新:标准SQL和最新表格:

SELECT TIMESTAMP(CONCAT(year,'-',mo,'-',da)) day, AVG(min) min, AVG(max) max, AVG(IF(prcp=99.99,0,prcp)) prcp
FROM `bigquery-public-data.noaa_gsod.gsod2016`
WHERE stn='722540' AND wban='13904'
GROUP BY 1
ORDER BY day

额外的例子,展示芝加哥在这个十年中最冷的几天:

#standardSQL
SELECT year, FORMAT('%s%s',mo,da) day ,min
FROM `fh-bigquery.weather_gsod.stations` a
JOIN `bigquery-public-data.noaa_gsod.gsod201*` b
ON a.usaf=b.stn AND a.wban=b.wban
WHERE name='CHICAGO/O HARE ARPT'
AND min!=9999.9
AND mo<'03'
ORDER BY 1,2

要获取任何城市的历史天气数据,首先我们需要找到在该城市报告的气象站。表格[fh-bigquery: weather_gsod.stations]包含已知站点的名称、它们所在的州(如果在美国)、国家和其他详细信息。

因此,要查找奥斯汀市的所有气象站,我们可以使用以下查询:

SELECT state, name, lat, lon
FROM [fh-bigquery:weather_gsod.stations] 
WHERE country='US' AND state='TX' AND name CONTAINS 'AUST'
LIMIT 10

在此输入图像描述

这种方法有两个问题需要解决:

  • 并非所有已知的站点都包含在该表中 - 我需要获取更新版本的此文件。因此,如果您在这里找不到要查找的站点,请不要放弃。
  • 并非在该文件中找到的每个站点都在每年运营 - 因此我们需要找到在我们寻找的年份期间具有数据的站点。

为了解决第二个问题,我们需要将站点表与我们正在寻找的实际数据连接起来。以下查询查找奥斯汀周围的站点,列 c 查看2015年有多少天具有实际数据:

SELECT state, name, FIRST(a.wban) wban, FIRST(a.stn) stn, COUNT(*) c, INTEGER(SUM(IF(prcp=99.99,0,prcp))) rain, FIRST(lat) lat, FIRST(lon) long
FROM [fh-bigquery:weather_gsod.gsod2015] a
JOIN [fh-bigquery:weather_gsod.stations] b 
ON a.wban=b.wban
AND a.stn=b.usaf
WHERE country='US' AND state='TX' AND name CONTAINS 'AUST'
GROUP BY 1,2
LIMIT 10

输入图像描述

太好了!我们找到了2015年奥斯汀市有数据的四个气象站。

请注意,我们必须以特殊方式处理“降雨”:当一个气象站不监测降雨时,它会将其标记为99.99而非null。我们的查询过滤掉了这些数值。

现在我们知道这些气象站的stn和wban编号,我们可以选择任何一个并可视化结果:

SELECT TIMESTAMP('2015'+mo+da) day, AVG(min) min, AVG(max) max, AVG(IF(prcp=99.99,0,prcp)) prcp
FROM [fh-bigquery:weather_gsod.gsod2015]
WHERE stn='722540' AND wban='13904'
GROUP BY 1
ORDER BY day

在此输入图片描述


谢谢!一个问题:在Google BigQuery仪表板中,有没有一种_简单_的方法可以获取所有年份的数据?在查询中列出所有表名(从gsod1929gsod2016)是一项相当冗长的任务:( - iTurki
表格查询可以帮助解决这个问题。请发布一个新问题,以获得完整的回答和示例 :) - Felipe Hoffa
不要认为它会“每天更新”,因为最近的日期是“2020-08-18”。 - thorr18
Felipe已经不再在Google工作,所以我怀疑这个答案现在是否可接受。 fh-bigquery项目和数据仍然存在,但我认为它将永远不会更新。 - Preston Marshall

3

现在除了Felipe的“官方”公共数据集之外,还有一个官方的NOAA BigQuery数据集。这里有一篇描述它的博客文章

以下是获取2016年8月15日最低温度的示例:

SELECT
  name, 
  value/10 AS min_temperature,
  latitude,
  longitude
FROM
  [bigquery-public-data:ghcn_d.ghcnd_stations] AS stn
JOIN
  [bigquery-public-data:ghcn_d.ghcnd_2016] AS wx
ON
  wx.id = stn.id
WHERE
  wx.element = 'TMIN'
  AND wx.qflag IS NULL
  AND STRING(wx.date) = '2016-08-15'

返回:

enter image description here


1
感谢您提取数据并将其制作成公共表格。以下是一个BigQuery查询,返回了德克萨斯州每个站点2014年的总降雨量:
SELECT FIRST(name) AS station_name, stn, SUM(prcp) AS annual_precip
FROM [fh-bigquery:weather_gsod.gsod2014] gsod
JOIN [fh-bigquery:weather_gsod.stations] stations
ON gsod.wban=stations.wban AND gsod.stn=stations.usaf
WHERE state='TX' AND prcp != 99.99
GROUP BY stn

这将返回:

table of results

获取每个位置的雨天数量,并根据此进行排序:

SELECT FIRST(name) AS station_name, stn, SUM(prcp) AS annual_precip,     COUNT(prcp) AS rainy_days
FROM [fh-bigquery:weather_gsod.gsod2014] gsod
JOIN [fh-bigquery:weather_gsod.stations] stations
ON gsod.wban=stations.wban AND gsod.stn=stations.usaf
WHERE state='TX' AND prcp != 99.99 AND prcp > 0
GROUP BY stn
ORDER BY rainy_days DESC

出现了 这些结果


0

使用车站名称是不可靠的。此外,使用新的bigquery功能进行地理空间查询很困难,因为城市边界没有清晰的形状(如圆形或矩形)。

因此,我找到了解决您问题的最佳方案,即使用反向地理编码,请求Google Maps API根据每个车站的纬度/经度坐标生成地址、州、城市和县。

以下是美国的结果CSV文件(StationNumber、Lat、Lon、Address、State、City、County、Zip),您会注意到98%的车站都在美国: https://gist.github.com/orcaman/a3e23c47489705dff93aace2e35f57d3

以下是代码,如果您想在美国以外的站点上重新运行它(使用golang): https://gist.github.com/orcaman/8de55f14f1c70ef5b0c124cf2fb7d9d1


谢谢你分享这个!你是否考虑分享 BigQuery 中的表格呢? - Felipe Hoffa
1
我更新了我的答案 - 现在使用按位置聚集的表格来避免名称不可靠性问题。同时查询数据也有很大的节省! - Felipe Hoffa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接