我有一个包含两列的数据框:countries
和year
。 countries
列是JSON,格式为:
[{'continent': 'europe',
'country': 'Yugoslavia',
'income': None,
'life_exp': None,
'population': 4687422},
{'continent': 'asia',
'country': 'United Korea (former)',
'income': None,
'life_exp': None,
'population': 13740000},
{'continent': 'asia',
'country': 'Tokelau',
'income': None,
'life_exp': None,
'population': 1009},
...
如何将该数据框转换为类似的内容:
continent | country | income | life_exp | population | year
----------+---------+--------+----------+------------+-------
europe | Yugos | None | None | 4600000 | 1800
asia | Korea | None ||None | 13000000 | 1800
asia | Tokelau | None | None | 1009 | 1800
是将JSON列分为几行及其相应的列,并添加与该行相对应的年份?
我在该列上使用了json_normalize()
,它为我提供了我需要的列,但我不知道如何在末尾添加年份
编辑: 这是我的原始数据框:
df = pd.read_json('data.json')
print(df-head())
countries year
0 [{'continent': 'europe', 'country': 'Yugoslavi... 1800
1 [{'continent': 'europe', 'country': 'Svalbard'... 1801
2 [{'continent': 'europe', 'country': 'Svalbard'... 1802
3 [{'continent': 'asia', 'country': 'Wallis et F... 1803
4 [{'continent': 'asia', 'country': 'Wallis et F... 1804
“国家/地区”列是包含多行数据的JSON,年份适用于所有数据,那么如何将其转换为包含所有行和每一行中对应年份的数据框?
我知道,如果我执行pd.DataFrame(df.countries[0])
,将产生第一行所有国家/地区的数据框,但是我不知道如何将年份添加到新列中。我认为可以这样做,但是我也想必须有一种更有效的方法
编辑:
此循环会产生我需要的结果,但我认为它效率很低:
new_df = pd.DataFrame(columns=['continent', 'country', 'income', 'life_exp', 'population', 'year'])
for i in range(len(old_df)):
temp_df = pd.DataFrame(old_df.countries[i])
temp_df['year'] = old_df.year[i]
new_df = new_df.append(temp_df)
肯定有更好的方法吧?
答案 0 :(得分:0)
将.join
与pd.json_normalize
一起使用
例如:
df = pd.DataFrame(data)
df = df.join(pd.json_normalize(df.pop('countries')))
print(df)
根据评论编辑
df = pd.DataFrame(data).explode('countries')
df = df.join(pd.json_normalize(df.pop('countries')))
print(df)
输出:
year continent country income life_exp population
0 1800 europe Yugoslavia None None 4687422
1 1801 asia United Korea (former) None None 13740000
2 1802 asia Tokelau None None 1009
答案 1 :(得分:0)
您可以尝试使用explode
:
df=df.explode('countries')
#we add to each dictionary the respective value of year with key 'year'
df['countries']=[{**dc,**{'year':y}} for dc,y in zip(df['countries'],df['year'])]
pd.DataFrame(df['countries'].tolist())
示例:
j = [{'continent': 'europe',
'country': 'Yugoslavia',
'income': None,
'life_exp': None,
'population': 4687422},
{'continent': 'asia',
'country': 'United Korea (former)',
'income': None,
'life_exp': None,
'population': 13740000}]
df=pd.DataFrame({'countries':[j,j],'year':[1800,1900]})
print(df)
df=df.explode('countries')
print(df)
#Here we add the key 'year' with the respective year row value to each dictionary
df['countries']=[{**dc,**{'year':y}} for dc,y in zip(df['countries'],df['year'])]
print(df['countries'])
finaldf=pd.DataFrame(df['countries'].tolist())
print(finaldf)
输出:
original df:
countries year
0 [{'continent': 'europe', 'country': 'Yugoslavi... 1800
1 [{'continent': 'europe', 'country': 'Yugoslavi... 1900
df(after explode):
countries year
0 {'continent': 'europe', 'country': 'Yugoslavia... 1800
0 {'continent': 'asia', 'country': 'United Korea... 1800
1 {'continent': 'europe', 'country': 'Yugoslavia... 1900
1 {'continent': 'asia', 'country': 'United Korea... 1900
df.countries(with year added):
0 {'continent': 'europe', 'country': 'Yugoslavia', 'income': None, 'life_exp': None, 'population': 4687422, 'year': 1800}
0 {'continent': 'asia', 'country': 'United Korea (former)', 'income': None, 'life_exp': None, 'population': 13740000, 'year': 1800}
1 {'continent': 'europe', 'country': 'Yugoslavia', 'income': None, 'life_exp': None, 'population': 4687422, 'year': 1900}
1 {'continent': 'asia', 'country': 'United Korea (former)', 'income': None, 'life_exp': None, 'population': 13740000, 'year': 1900}
Name: countries, dtype: object
finaldf
continent country income life_exp population year
0 europe Yugoslavia None None 4687422 1800
1 asia United Korea (former) None None 13740000 1800
2 europe Yugoslavia None None 4687422 1900
3 asia United Korea (former) None None 13740000 1900
答案 2 :(得分:0)
您可以使用apply方法进行矢量化,然后从country
列中获取相应的标记。由于您有一个名为国家的密钥,因此请在for
循环之外使用它。看起来像这样
attribute = ['continent', 'income', 'life_exp', 'population']
for attr in attribute:
df[attr] = df.country.apply(lambda x: x[attr])
df['country'] = df.country.apply(lambda x: x['country'])
这样做的好处是您只循环使用属性的数量,而不是遍历每个项目。