遍历 JSON 并附加到数据帧中

问题描述

我正在从 weatherstack API 获取天气预报数据。

params = {
    'access_key': 'enter_key_here','query': 'Montreal','forecast_days': '2',#two days forecast
    'hourly': '1'                       #API to return weather data split hourly
}

api_result = requests.get('https://api.weatherstack.com/forecast',params)

api_response = api_result.json()

api_response

输出如下:

{'request': {'type': 'City','query': 'Montreal,Canada','language': 'en','unit': 'm'},'location': {'name': 'Montreal','country': 'Canada','region': 'Quebec','lat': '45.500','lon': '-73.583','timezone_id': 'America/Toronto','localtime': '2021-05-11 13:08','localtime_epoch': 1620738480,'utc_offset': '-4.0'},'current': {'observation_time': '05:08 PM','temperature': 11,'weather_code': 122,'weather_icons': ['https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0004_black_low_cloud.png'],'weather_descriptions': ['Overcast'],'wind_speed': 31,'wind_degree': 230,'wind_dir': 'SW','pressure': 1012,'precip': 1,'humidity': 58,'cloudcover': 100,'feelslike': 8,'uv_index': 2,'visibility': 14,'is_day': 'yes'},'forecast': {'2021-05-11': {'date': '2021-05-11','date_epoch': 1620691200,'astro': {'sunrise': '05:28 AM','sunset': '08:14 PM','moonrise': '05:35 AM','moonset': '08:14 PM','moon_phase': 'Waxing Crescent','moon_illumination': 7},'mintemp': 6,'maxtemp': 13,'avgtemp': 8,'totalsNow': 0,'sunhour': 12.4,'uv_index': 6,'hourly': [{'time': '0','temperature': 9,'wind_speed': 16,'wind_degree': 240,'wind_dir': 'WSW','weather_code': 119,'weather_icons': ['https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0003_white_cloud.png'],'weather_descriptions': ['Cloudy'],'precip': 0.1,'humidity': 74,'visibility': 10,'cloudcover': 75,'heatindex': 9,'dewpoint': 5,'windchill': 7,'windgust': 23,'feelslike': 7,'chanceofrain': 43,'chanceofremdry': 31,'chanceofwindy': 0,'chanceofovercast': 86,'chanceofsunshine': 5,'chanceoffrost': 0,'chanceofhightemp': 0,'chanceoffog': 0,'chanceofsNow': 0,'chanceofthunder': 0,'uv_index': 1},{'time': '300','temperature': 8,'wind_speed': 15,'wind_degree': 247,'precip': 0,'humidity': 83,'cloudcover': 88,'heatindex': 8,'dewpoint': 6,'windchill': 6,'windgust': 21,'feelslike': 6,'chanceofrain': 0,'chanceofremdry': 89,'chanceofovercast': 88,'chanceofsunshine': 15,{'time': '600','temperature': 7,'wind_speed': 17,'wind_degree': 239,'humidity': 90,'heatindex': 7,'windchill': 4,'windgust': 24,'feelslike': 4,'chanceofremdry': 84,'chanceofovercast': 90,'uv_index': 2},{'time': '900','wind_speed': 21,'wind_degree': 248,'weather_code': 296,'weather_icons': ['https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0017_cloudy_with_light_rain.png'],'weather_descriptions': ['Light rain'],'precip': 0.5,'humidity': 88,'windchill': 5,'windgust': 27,'feelslike': 5,'chanceofrain': 28,'chanceofremdry': 57,'chanceofovercast': 83,'chanceofsunshine': 11,{'time': '1200','temperature': 10,'wind_speed': 24,'wind_degree': 259,'weather_code': 293,'weather_descriptions': ['Patchy light rain'],'precip': 1.3,'humidity': 71,'visibility': 9,'cloudcover': 85,'heatindex': 10,'dewpoint': 4,'windgust': 28,'chanceofrain': 82,'chanceofremdry': 0,'chanceofovercast': 87,'chanceofsunshine': 0,{'time': '1500','temperature': 12,'wind_speed': 23,'wind_degree': 273,'wind_dir': 'W','weather_code': 176,'weather_icons': ['https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png'],'weather_descriptions': ['Patchy rain possible'],'precip': 0.7,'humidity': 49,'cloudcover': 66,'heatindex': 12,'dewpoint': 2,'windchill': 10,'feelslike': 10,'chanceofrain': 79,'chanceofovercast': 89,'uv_index': 3},{'time': '1800','wind_degree': 277,'weather_code': 116,'weather_icons': ['https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png'],'weather_descriptions': ['Partly cloudy'],'humidity': 54,'pressure': 1011,'cloudcover': 73,'heatindex': 11,'windchill': 9,'windgust': 26,'feelslike': 9,'chanceofrain': 56,'chanceofremdry': 30,'chanceofovercast': 68,'chanceofsunshine': 27,'uv_index': 4},{'time': '2100','weather_icons': ['https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0025_light_rain_showers_night.png'],'humidity': 75,'pressure': 1013,'cloudcover': 61,'dewpoint': 3,'chanceofrain': 22,'chanceofremdry': 60,'chanceofovercast': 59,'chanceofsunshine': 53,'uv_index': 1}]},'2021-05-12': {'date': '2021-05-12','date_epoch': 1620777600,'astro': {'sunrise': '05:27 AM','sunset': '08:15 PM','moonrise': '05:59 AM','moonset': '09:19 PM','moon_illumination': 14},'mintemp': 5,'maxtemp': 15,'avgtemp': 10,'sunhour': 11.4,'uv_index': 4,'temperature': 6,'wind_degree': 266,'humidity': 85,'heatindex': 6,'windchill': 3,'feelslike': 3,'chanceofrain': 44,'chanceofremdry': 29,'chanceofovercast': 92,'chanceofsunshine': 4,'wind_speed': 13,'wind_degree': 270,'cloudcover': 98,'windgust': 18,'chanceofremdry': 88,'chanceofsunshine': 13,'wind_speed': 11,'wind_degree': 293,'wind_dir': 'WNW','humidity': 81,'pressure': 1016,'cloudcover': 94,'windgust': 16,'chanceofremdry': 91,'wind_degree': 324,'wind_dir': 'NW','humidity': 60,'pressure': 1018,'windchill': 8,'windgust': 15,'chanceofrain': 23,'chanceofremdry': 61,'chanceofovercast': 93,'chanceofsunshine': 7,'temperature': 14,'wind_speed': 14,'wind_degree': 344,'wind_dir': 'NNW','humidity': 42,'cloudcover': 95,'heatindex': 14,'dewpoint': 1,'windchill': 13,'feelslike': 13,'chanceofrain': 66,'temperature': 15,'wind_speed': 10,'wind_degree': 332,'humidity': 39,'cloudcover': 72,'heatindex': 15,'windchill': 14,'windgust': 12,'feelslike': 14,'chanceofrain': 41,'chanceofremdry': 28,'chanceofovercast': 72,'chanceofsunshine': 23,'wind_speed': 6,'wind_degree': 271,'humidity': 44,'pressure': 1019,'cloudcover': 44,'windgust': 9,'chanceofremdry': 85,'chanceofovercast': 37,'chanceofsunshine': 75,'humidity': 56,'pressure': 1020,'cloudcover': 41,'windchill': 12,'windgust': 10,'feelslike': 12,'chanceofsunshine': 82,'uv_index': 1}]}}}

如何遍历此输出并创建一个新的数据框,如下所示: (并且只获取日期时间小时和雨量值)

日期 在时间 0 的沉淀 在时间 300 时的沉淀 ...
2021-05-11 0.1 0 ...
2021-05-12 0.1 0 ...
... ... ... ...

另外,我想将日期列转换为 Month Day,Year。 IE。 2021-05-11 -> 2021 年 5 月 5 日。我尝试使用

df['Date'] = datetime.datetime.strftime('%b %d,%Y')

然后

df['Date'] = pandas.to_datetime(df['Date'])

但我收到此错误

AttributeError: type object 'datetime.datetime' has no attribute 'datetime'

解决方法

创建数据框

这将创建一个包含所需数据和列名的数据框。

import pandas as pd

### code to get data

forecast={}

for date in api_response['forecast']:
  precip = {f"precip at time {api_response['forecast'][date]['hourly'][hour]['time']}":
              api_response['forecast'][date]['hourly'][hour]['precip']  for hour in range(0,8)}
  forecast[date] = precip

df  = pd.DataFrame.from_dict(forecast,orient='index',dtype=float).reset_index()
df.rename(columns={'index':'Date'},inplace=True)

print(df)

创建数据帧和格式标题

如果您想要 HH:MM 格式的时间,请对代码进行这些更改/添加。

import json
import pandas as pd

### code to get data

forecast={}

for date in api_response['forecast']:
  precip = {api_response['forecast'][date]['hourly'][hour]['time']:
              api_response['forecast'][date]['hourly'][hour]['precip']  for hour in range(0,dtype=float).reset_index()

cols = ['Date' if col=='index' else f'precip at time {col.zfill(4)[:2]+":"+col.zfill(4)[2:]}'  for col in df.columns]

df.columns = cols

print(df)

更改日期列格式

要更改 Date 列的格式,我们首先需要将其转换为 datetime,我们可以使用 pd.to_datetime 来完成。

然后我们可以链接 strftime 以获得所需的格式 May 05,2021

有关可以与 strftime 一起使用的指令的完整列表,请参阅 here

df['Date'] = pd.to_datetime(df['Date']).dt.strftime('%B %d,%Y')