json이라고 하는 컬럼이 있는 판다의 데이터 프레임을 평평하게 하려면 어떻게 해야 합니까?
데이터 프레임이 있습니다.df
데이터베이스에서 데이터를 로드합니다.대부분의 열은 json 문자열이고 일부는 json 목록입니다.예를 들어 다음과 같습니다.
id name columnA columnB
1 John {"dist": "600", "time": "0:12.10"} [{"pos": "1st", "value": "500"},{"pos": "2nd", "value": "300"},{"pos": "3rd", "value": "200"}, {"pos": "total", "value": "1000"}]
2 Mike {"dist": "600"} [{"pos": "1st", "value": "500"},{"pos": "2nd", "value": "300"},{"pos": "total", "value": "800"}]
...
보시는 것처럼 모든 행이 열의 json 문자열에서 동일한 수의 요소가 있는 것은 아닙니다.
제가 해야 할 일은 정상 컬럼을 다음과 같이 유지하는 것입니다.id
그리고.name
다음과 같이 json 열을 평평하게 합니다.
id name columnA.dist columnA.time columnB.pos.1st columnB.pos.2nd columnB.pos.3rd columnB.pos.total
1 John 600 0:12.10 500 300 200 1000
2 Mark 600 NaN 500 300 Nan 800
사용해보았습니다.json_normalize
다음과 같이 합니다.
from pandas.io.json import json_normalize
json_normalize(df)
하지만 에 몇 가지 문제가 있는 것 같습니다.keyerror
올바른 방법은 무엇입니까?
커스텀 함수를 사용하여 데이터를 올바른 형식으로 취득함으로써 다시 사용하는 솔루션을 다음에 나타냅니다.json_normalize
기능.
import ast
from pandas.io.json import json_normalize
def only_dict(d):
'''
Convert json string representation of dictionary to a python dict
'''
return ast.literal_eval(d)
def list_of_dicts(ld):
'''
Create a mapping of the tuples formed after
converting json strings of list to a python list
'''
return dict([(list(d.values())[1], list(d.values())[0]) for d in ast.literal_eval(ld)])
A = json_normalize(df['columnA'].apply(only_dict).tolist()).add_prefix('columnA.')
B = json_normalize(df['columnB'].apply(list_of_dicts).tolist()).add_prefix('columnB.pos.')
마지막으로,DFs
공통 인덱스에서 다음 정보를 얻습니다.
df[['id', 'name']].join([A, B])
편집:- @MartijnPieters의 코멘트에 의하면, 데이터 소스가 JSON인 것을 알고 있는 경우에 비해 json 문자열을 디코딩하는 것이 권장됩니다.
가장 빠른 것은 다음과 같습니다.
import pandas as pd
import json
json_struct = json.loads(df.to_json(orient="records"))
df_flat = pd.io.json.json_normalize(json_struct) #use pd.io.json
TL;DR 다음 기능을 복사 붙여넣고 다음과 같이 사용합니다.flatten_nested_json_df(df)
이것이 제가 생각할 수 있는 가장 일반적인 기능입니다.
def flatten_nested_json_df(df):
df = df.reset_index()
print(f"original shape: {df.shape}")
print(f"original columns: {df.columns}")
# search for columns to explode/flatten
s = (df.applymap(type) == list).all()
list_columns = s[s].index.tolist()
s = (df.applymap(type) == dict).all()
dict_columns = s[s].index.tolist()
print(f"lists: {list_columns}, dicts: {dict_columns}")
while len(list_columns) > 0 or len(dict_columns) > 0:
new_columns = []
for col in dict_columns:
print(f"flattening: {col}")
# explode dictionaries horizontally, adding new columns
horiz_exploded = pd.json_normalize(df[col]).add_prefix(f'{col}.')
horiz_exploded.index = df.index
df = pd.concat([df, horiz_exploded], axis=1).drop(columns=[col])
new_columns.extend(horiz_exploded.columns) # inplace
for col in list_columns:
print(f"exploding: {col}")
# explode lists vertically, adding new columns
df = df.drop(columns=[col]).join(df[col].explode().to_frame())
new_columns.append(col)
# check if there are still dict o list fields to flatten
s = (df[new_columns].applymap(type) == list).all()
list_columns = s[s].index.tolist()
s = (df[new_columns].applymap(type) == dict).all()
dict_columns = s[s].index.tolist()
print(f"lists: {list_columns}, dicts: {dict_columns}")
print(f"final shape: {df.shape}")
print(f"final columns: {df.columns}")
return df
열에 중첩된 목록 및/또는 딕트가 있을 수 있는 데이터 프레임을 가져와서 해당 열을 반복적으로 확장/확대합니다.
팬더'는 사전을 폭발시키기 위해, 팬더는 목록을 폭발시키기 위해 사용합니다.
심플한 사용법
# Test
df = pd.DataFrame(
columns=['id','name','columnA','columnB'],
data=[
[1,'John',{"dist": "600", "time": "0:12.10"},[{"pos": "1st", "value": "500"},{"pos": "2nd", "value": "300"},{"pos": "3rd", "value": "200"}, {"pos": "total", "value": "1000"}]],
[2,'Mike',{"dist": "600"},[{"pos": "1st", "value": "500"},{"pos": "2nd", "value": "300"},{"pos": "total", "value": "800"}]]
])
flatten_nested_json_df(df)
가장 효율적인 방법은 아니며 데이터 프레임의 인덱스를 재설정하는 부작용도 있지만 작업을 수행할 수 있습니다.얼마든지 조정해 주세요.
평평하게 하기 위한 커스텀 함수를 작성하다columnB
그 후pd.concat
def flatten(js):
return pd.DataFrame(js).set_index('pos').squeeze()
pd.concat([df.drop(['columnA', 'columnB'], axis=1),
df.columnA.apply(pd.Series),
df.columnB.apply(flatten)], axis=1)
언급URL : https://stackoverflow.com/questions/39899005/how-to-flatten-a-pandas-dataframe-with-some-columns-as-json
'programing' 카테고리의 다른 글
구성요소는 어느 수준에서 Stores in Flux의 엔티티를 읽어야 합니까? (0) | 2023.03.31 |
---|---|
Android에서 json 문자열을 해석하는 방법은 무엇입니까? (0) | 2023.03.31 |
JavaScript 및 ES6, "글로벌" 변수 (0) | 2023.03.31 |
React Functional 컴포넌트: 함수와 컴포넌트로 호출 (0) | 2023.03.31 |
miniated javascript stack trace를 소스 맵에 대해 실행하여 적절한 오류를 얻으려면 어떻게 해야 합니까? (0) | 2023.03.31 |