将 JSON 文件转换为 Pandas 数据框
Posted
技术标签:
【中文标题】将 JSON 文件转换为 Pandas 数据框【英文标题】:Convert JSON file to Pandas dataframe 【发布时间】:2020-02-29 19:24:37 【问题描述】:我想将 JSON 转换为 Pandas 数据框。
我的 JSON 看起来像: 喜欢:
"country1":
"AdUnit1":
"floor_price1":
"feature1":1111,
"feature2":1112
,
"floor_price2":
"feature1":1121
,
"AdUnit2":
"floor_price1":
"feature1":1211
,
"floor_price2":
"feature1":1221
,
"country2":
"AdUnit1":
"floor_price1":
"feature1":2111,
"feature2":2112
我使用以下代码从 GCP 读取文件:
project = Context.default().project_id
sample_bucket_name = 'my_bucket'
sample_bucket_path = 'gs://' + sample_bucket_name
print('Object: ' + sample_bucket_path + '/json_output.json')
sample_bucket = storage.Bucket(sample_bucket_name)
sample_bucket.create()
sample_bucket.exists()
sample_object = sample_bucket.object('json_output.json')
list(sample_bucket.objects())
json = sample_object.read_stream()
我的目标是获得如下所示的 Pandas 数据框:
我尝试使用json_normalize,但没有成功。
【问题讨论】:
pd.read_json
怎么样?
我试过了,结果不好:c2n.me/44pYvfb
看看this的回答,因为我认为你需要先将json“展平”才能使用pd.read_json(json.dumps(json_dictionary))
【参考方案1】:
你可以试试这个方法:
from google.cloud import storage
import pandas as pd
storage_client = storage.Client()
bucket = storage_client.get_bucket('test-mvladoi')
blob = bucket.blob('file')
read_output = blob.download_as_string()
data = json.loads(read_output)
data_norm = json_normalize(data, max_level=5)
df = pd.DataFrame(columns=['col1', 'col2', 'col3', 'col4', 'col5'])
i = 0
for col in b.columns:
a,c,d,e = col.split('.')
df.loc[i] = [a,c,d,e,b[col][0]]
i = i + 1
print(df)
【讨论】:
我在 Google 数据实验室工作,from google.cloud import storage
存在一些问题
试过了。 AttributeError: module 'google.datalab.storage' has no attribute 'Client'
他们处理存储的方式不同:mybucket = storage.Bucket('BUCKET_NAME'), blob = mybucket.object('file') 在网上看【参考方案2】:
不是最好的方法,但它的工作。此外,您还应该修改仅从此 awnser 中挑选的 flatten 函数
test =
"country1":
"AdUnit1":
"floor_price1":
"feature1":1111,
"feature2":1112
,
"floor_price2":
"feature1":1121
,
"AdUnit2":
"floor_price1":
"feature1":1211
,
"floor_price2":
"feature1":1221
,
"country2":
"AdUnit1":
"floor_price1":
"feature1":2111,
"feature2":2112
from collections import defaultdict
import pandas as pd
import collections
def flatten(d, parent_key='', sep='_'):
items = []
for k, v in d.items():
new_key = parent_key + sep + k if parent_key else k
if isinstance(v, collections.MutableMapping):
items.extend(flatten(v, new_key, sep=sep).items())
else:
items.append((new_key, v))
return dict(items)
results = defaultdict(list)
colnames = ["col1", "col2", "col3", "col4", "col5", "col6"]
for key, value in flatten(test).items():
elements = key.split("_")
elements.append(value)
for colname, element in zip(colnames, elements):
results[colname].append(element)
df = pd.DataFrame(results)
print(df)
【讨论】:
【参考方案3】:你可以用这个:
def flatten_dict(d):
""" Returns list of lists from given dictionary """
l = []
for k, v in sorted(d.items()):
if isinstance(v, dict):
flatten_v = flatten_dict(v)
for my_l in reversed(flatten_v):
my_l.insert(0, k)
l.extend(flatten_v)
elif isinstance(v, list):
for l_val in v:
l.append([k, l_val])
else:
l.append([k, v])
return l
这个函数接收一个字典(包括值也可以是列表的嵌套)并将其展平为列表列表。
那么,你可以简单地:
df = pd.DataFrame(flatten_dict(my_dict))
my_dict
是您的 JSON 对象。
以您为例,运行print(df)
时得到的是:
0 1 2 3 4
0 country1 AdUnit1 floor_price1 feature1 1111
1 country1 AdUnit1 floor_price1 feature2 1112
2 country1 AdUnit1 floor_price2 feature1 1121
3 country1 AdUnit2 floor_price1 feature1 1211
4 country1 AdUnit2 floor_price2 feature1 1221
5 country2 AdUnit1 floor_price1 feature1 2111
6 country2 AdUnit1 floor_price1 feature2 2112
当你创建数据框时,你可以命名你的列和索引
【讨论】:
【参考方案4】:嵌套的 JSON 总是很难正确处理。
几个月前,我想出了一种方法来提供一个“通用答案”,使用来自here 的编写精美的flatten_json_iterative_solution:它迭代地解包每个级别给定的 json。
然后可以简单地将其转换为 Pandas.Series 然后 Pandas.DataFrame 像这样:
df = pd.Series(flatten_json_iterative_solution(dict(json_))).to_frame().reset_index()
Intermediate Dataframe result
可以很容易地执行一些数据转换来拆分您要求的列名中的索引:
df[["index", "col1", "col2", "col3", "col4"]] = df['index'].apply(lambda x: pd.Series(x.split('_')))
Final result
【讨论】:
以上是关于将 JSON 文件转换为 Pandas 数据框的主要内容,如果未能解决你的问题,请参考以下文章