Closed yijunwang0805 closed 4 years ago
你好,由于不同省份的城市数量不定,所以丁香园和我都是选择了在cities
中储存列表来保证城市长度的可变性,但在pandas读取数据时确实不太方便。
在数据挖掘过程中,载入数据必定会碰到类似的问题,大部分的数据都不是可以直接载入的,所以我下面的内容可能不止针对这一个问题,而是针对类似的问题的一个解决方案。
事实上,这个返回数据中的results
也是一个list
,这个list
中的每一个元素都是一个字典,pandas在读取results
时,会直接将list
中的每一个字典作为一行或一列。然而,其中cities
又是一个字典的列表,而pandas无法直接对这个数据进行解析了。
大致的数据结构如下:
"results": [
{
"cities": [
{
... # 这个城市内各种参数
},
... # 其他城市的字典
],
... # 这个省份的其他变量
},
... # 其他省份
]
因此,如果希望能够解析这个数据,需要从最底层的字典列表开始逐层往上展开,即先考虑读取cities
。
cities
如果希望能够读取cities
中的列表,将cities
面的每一个字典都变成单独的一行,可以直接使用
temp = pd.DataFrame(r.json()['results'][0]['cities'])
这样的方法由于在results
处取[0]
,仅能够载入第一个省份字典中的cities
数据,无法载入该省份除cities
以外的数据,但是已经能够将这个省份内的所有城市数据载入一个DataFrame。
province
在载入了cities
之后,已经有一个基础的DataFrame,其中每一行是一个省份的所有城市数据,但是并不包括这个省份的其他数据,因此,需要在这个DataFrame里面添加其他列,来填充这个省份的数据。
# 其他变量也可以通过此方法处理
temp['province_confirmedCount'] = r.json()['results'][0]['confirmedCount']
在上述操作完成之后,现在的这个DataFrame里面已经包括了这个省份的所有信息。只需要使用一个循环,针对results
里面的每一个字典都进行上述的操作,就能载入所有省份的信息,最后将结果汇总在一张大表中即可。
大致的逻辑如下:
data = pd.DataFrame()
for province in r.json()['results']:
temp = pd.DataFrame(province['cities'])
temp['province_confirmedCount'] = province['confirmedCount']
... # 载入其他变量
data = data.concat([data, temp], ignore_index=True) # 将每一个省份的数据合并到总数据中
最终即可完成数据载入工作。
另外,可以参考数据仓库的script.py文件,里面的csv_dumper()
函数就是上述过程的完整代码。
这份代码仅包括了对cities
的解析,没有对国家和港澳台地区的解析(因为这些地区没有cities
,我在代码中直接剔除了所有不带cities
的数据),如果能理解上面的内容,再加上其他国家和港澳台地区的数据应该也不太困难。
你好, 我用上述方法提取了数据,现在发现似乎少了时间变量。
import pandas as pd
import os
import numpy
import requests
url = 'https://lab.isaaclin.cn/nCoV/api/area?latest=1'
r = requests.request('GET', url)
data = r.json()
df = pd.DataFrame.from_records(data['results'])
from datetime import datetime
df
data = pd.DataFrame()
temp = pd.DataFrame(r.json()['results'][0]['cities'])
# # 其他变量也可以通过此方法处理
temp['province_confirmedCount'] = r.json()['results'][0]['confirmedCount']
# data = pd.DataFrame()
from pandas import concat
for province in r.json()['results']:
temp = pd.DataFrame(province['cities'])
temp['province_confirmedCount'] = province['confirmedCount']
data = pd.concat([data, temp], ignore_index=True) # 将每一个省份的数据合并到总数据中
Anaconda 警告了
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:9: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version
of pandas will change to not sort by default.
To accept the future behavior, pass 'sort=False'.
To retain the current behavior and silence the warning, pass 'sort=True'.
if __name__ == '__main__':
最后提出来才424行,
cityEnglishName cityName confirmedCount curedCount \
0 Chengdu 成都 143.0 93.0
1 Garzê Tibetan Autonomous Prefecture 甘孜州 78.0 53.0
2 Dazhou 达州 42.0 28.0
3 Nanchong 南充 39.0 30.0
4 Bazhong 巴中 24.0 18.0
.. ... ... ... ...
419 Anshun 安顺 4.0 4.0
420 Qianxinan 黔西南州 4.0 4.0
421 Lhasa 拉萨 1.0 1.0
422 Xining 西宁 15.0 15.0
423 Haibei 海北州 3.0 3.0
currentConfirmedCount deadCount locationId province_confirmedCount \
0 47.0 3.0 510100.0 538
1 25.0 0.0 513300.0 538
2 14.0 0.0 511700.0 538
3 9.0 0.0 511300.0 538
4 6.0 0.0 511900.0 538
.. ... ... ... ...
419 0.0 0.0 520400.0 146
420 0.0 0.0 522300.0 146
421 0.0 0.0 540100.0 1
422 0.0 0.0 630100.0 18
423 0.0 0.0 632200.0 18
suspectedCount
0 0.0
1 0.0
2 0.0
3 0.0
4 0.0
.. ...
419 0.0
420 0.0
421 0.0
422 0.0
423 0.0
[424 rows x 9 columns]
目前没找到有效的提取方法,一直在用手动输入城市名字url = 'https://lab.isaaclin.cn/nCoV/api/area?latest=0&province=北京市
一个一个城市地提取
@yijunwang0805
url = 'https://lab.isaaclin.cn/nCoV/api/area?latest=0'
才能够提取到所有时间序列数据,否则只能提取到目前最新数据;data['results']
建立DataFrame,一开始直接从cities来处理比较合适,从最下层级开始往上拆解数据;concat
方法在未来的版本会修改sort
参数的默认属性,因此建议用户直接在函数内定义sort
变量的值,否则有可能会因为未来的版本迭代而影响以前的代码,具体的内容可以参考StackOverflow,此处sort
设为True
或者False
均可,不会影响结果。如果方便的话可以发一下完整的代码,我可以来看看。或者也可以参考我的script.py文件。
Hi, 现在好像有个不一样的报错了。(其实script.py文件我看了好几次,但我的代码理解能力还是很有限的)
import pandas as pd
import os
import numpy
import requests
url = 'https://lab.isaaclin.cn/nCoV/api/area?latest=0'
r = requests.request('GET', url)
data = r.json()
#df = pd.DataFrame.from_records(data['results'])
from datetime import datetime
#data = pd.DataFrame()
temp = pd.DataFrame(r.json()['results'][0]['cities'])
# # 其他变量也可以通过此方法处理
temp['province_confirmedCount'] = r.json()['results'][0]['confirmedCount']
# data = pd.DataFrame()
from pandas import concat
for province in r.json()['results']:
temp = pd.DataFrame(province['cities'])
temp['province_confirmedCount'] = province['confirmedCount']
data = pd.concat([data, temp], ignore_index=True) # 将每一个省份的数据合并到总数据中
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-25-58c98792dc3b> in <module>
17 temp = pd.DataFrame(province['cities'])
18 temp['province_confirmedCount'] = province['confirmedCount']
---> 19 data = pd.concat([data, temp], ignore_index=True) # 将每一个省份的数据合并到总数据中
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in concat(objs, axis, join, join_axes, ignore_index, keys, levels, names, verify_integrity, sort, copy)
253 verify_integrity=verify_integrity,
254 copy=copy,
--> 255 sort=sort,
256 )
257
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in __init__(self, objs, axis, join, join_axes, keys, levels, names, ignore_index, verify_integrity, copy, sort)
330 " only Series and DataFrame objs are valid".format(type(obj))
331 )
--> 332 raise TypeError(msg)
333
334 # consolidate
TypeError: cannot concatenate object of type '<class 'dict'>'; only Series and DataFrame objs are valid
Hi, 现在好像有个不一样的报错了。(其实script.py文件我看了好几次,但我的代码理解能力还是很有限的)
你的代码中由于data = r.json()
,导致data
是字典的格式,temp
是DataFrame的格式,无法使用concat
方法链接的。
我的示例代码里面最后一个代码块有这部分的内容,其中有一句data = pd.DataFrame()
,就是为了解决这个问题的。
你如果需要用data
变量存放r.json()
,则可以使用其他变量(如_data)初始化一个DataFrame,并且concat的时候使用_data = pd.concat([_data, temp], ignore_index=True)
已知用以下python代码能获取全国的数据
但当我们需要读取城市/区域的数据将
all
改成area
时输出嵌套着list,不知道如何解决?