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 |

