팬더와 함께 사전 열 분할/폭발
 i a  ipostgreSQL데이터베이스입니다.Python 2.7 python python frame Panda Data Frame 。그러나 이 데이터 프레임의 마지막 열에는 값 사전이 포함되어 있습니다. Frame " " " "df음음음같 뭇매하다
Station ID     Pollutants
8809           {"a": "46", "b": "3", "c": "12"}
8810           {"a": "36", "b": "5", "c": "8"}
8811           {"b": "2", "c": "7"}
8812           {"c": "11"}
8813           {"a": "82", "c": "15"}
DataFrame 'df2가 다음과 같이 보이도록 이 열을 다른 열로 분할해야 합니다.
Station ID     a      b       c
8809           46     3       12
8810           36     5       8
8811           NaN    2       7
8812           NaN    NaN     11
8813           82     NaN     15
제가 가지고 있는 가장 큰 문제는 리스트의 길이가 같지 않다는 것입니다.그러나 모든 목록에는 'a', 'b' 및 'c'의 동일한 세 가지 값만 포함됩니다.그리고 그것들은 항상 같은 순서로 나타난다('a' 첫째, 'b' 둘째, 'c' 셋째).
다음 코드는 내가 원하는 대로 작동하고 반환하는 데 사용됩니다(df2).
objs = [df, pandas.DataFrame(df['Pollutant Levels'].tolist()).iloc[:, :3]]
df2 = pandas.concat(objs, axis=1).drop('Pollutant Levels', axis=1)
print(df2)
지난주에 이 코드를 실행했는데 정상적으로 작동했어요.그런데 코드가 깨져서 [4]행에서 다음 오류가 나타납니다.
IndexError: out-of-bounds on slice (end) 
코드를 변경하지 않았는데 오류가 발생하였습니다.저는 이것이 제 방법이 견고하지 않거나 적절하지 못하기 때문이라고 생각합니다.
이 목록 열을 다른 열로 분할하는 방법에 대한 제안이나 지침을 주시면 감사하겠습니다.
 내 에는 : 제 edit edit edit edit edit edit edit edit edit.tolist()의 Unicode 문자열( .apply Unicode 문자열)이기 때문에 내 하지 않습니다.
#My data format 
u{'a': '1', 'b': '2', 'c': '3'}
#and not
{u'a': '1', u'b': '2', u'c': '3'}
.postgreSQL이 형식의 데이터베이스입니다.요?니코 를변 ?환 법? ???
하려면 , 「dict」를 합니다.df['Pollutant Levels'].map(eval)그 후 다음 솔루션을 사용하여 dict를 다른 열로 변환할 수 있습니다.
예를 하여 ""를 사용할 수 ..apply(pd.Series):
In [2]: df = pd.DataFrame({'a':[1,2,3], 'b':[{'c':1}, {'d':3}, {'c':5, 'd':6}]})
In [3]: df
Out[3]:
   a                   b
0  1           {u'c': 1}
1  2           {u'd': 3}
2  3  {u'c': 5, u'd': 6}
In [4]: df['b'].apply(pd.Series)
Out[4]:
     c    d
0  1.0  NaN
1  NaN  3.0
2  5.0  6.0
 할 수 있습니다.concat다음과 같이 입력합니다.
In [7]: pd.concat([df.drop(['b'], axis=1), df['b'].apply(pd.Series)], axis=1)
Out[7]:
   a    c    d
0  1  1.0  NaN
1  2  NaN  3.0
2  3  5.0  6.0
하면, 「이나 「이것」을 합니다.iloc 삭제:
In [15]: pd.concat([df.drop('b', axis=1), pd.DataFrame(df['b'].tolist())], axis=1)
Out[15]:
   a    c    d
0  1  1.0  NaN
1  2  NaN  3.0
2  3  5.0  6.0
꽤 오래된 질문인건 알지만, 답을 찾으러 왔어요.실제로 다음과 같은 방법을 사용하여 이를 보다 신속하게 수행할 수 있습니다.
import pandas as pd
df2 = pd.json_normalize(df['Pollutant Levels'])
이렇게 하면 비용이 많이 드는 기능을 적용할 필요가 없어집니다.
-  1레벨 dicts이 답변에서 Shijith가 수행한 타이밍 분석에 따르면:- df.join(pd.DataFrame(df.pop('Pollutants').values.tolist()))
- 다른 문제(컬럼 포함)는 해결되지 않습니다.list★★★★★★★★★★★★★★★★★」dicts다음 행과 같이 아래에 기재되어 있습니다.NaN네스트된 " " " "dicts.
 
- pd.json_normalize(df.Pollutants)하게 빠르다- df.Pollutants.apply(pd.Series)- 「 」를 .%%timeit행의 경우, 100만 행의 경우,.json_normalize.apply.
 
- 「 」를 .
- 를 읽는지,, API에서 반환된 데이터인지 하지 않을 수 .dict에 ''가 있습니다.dict★★★★★★★★★★★★★★★★★」str★★★★★★ 。- 열의 사전이 유형인 경우 또는 를 사용하여 다시 유형으로 변환해야 합니다.json.loads(…).
 
- 열의 사전이 유형인 경우 또는 를 사용하여 다시 유형으로 변환해야 합니다.
- 를 변환하기 위해 사용합니다.dicts, 를 사용하여, 를 참조해 주세요.keys및 ""로 합니다.values행의 경우.-  추추파(((((((((((((((((((:record_path&meta네스트된 '네스트된'을dicts.
 
-  추추파(((((((((((((((((((:
- 원래 Data Frame을 조합하기 위해 사용합니다.df를 사용하여pd.json_normalize- 인덱스가 정수(예시와 같이)가 아닌 경우 정규화 및 결합을 수행하기 전에 먼저 를 사용하여 정수 인덱스를 가져옵니다.
- pandas.DataFrame.pop지정된 컬럼을 기존 데이터 프레임에서 삭제하기 위해 사용합니다.그러면 나중에 를 사용하여 컬럼을 드롭할 필요가 없어집니다.
 
- 에 음음음음음음음음음음음음음 any any any any any any as as as as as as가 있는 NaN합니다.dict- df.Pollutants = df.Pollutants.fillna({i: {} for i in df.index})-  경우,'Pollutants'입니다. 사용'{}'.
- 또한 NaN으로 json_normalize하는 방법을 참조하십시오.
 
-  경우,
 
import pandas as pd
from ast import literal_eval
import numpy as np
data = {'Station ID': [8809, 8810, 8811, 8812, 8813, 8814],
        'Pollutants': ['{"a": "46", "b": "3", "c": "12"}', '{"a": "36", "b": "5", "c": "8"}', '{"b": "2", "c": "7"}', '{"c": "11"}', '{"a": "82", "c": "15"}', np.nan]}
df = pd.DataFrame(data)
# display(df)
   Station ID                        Pollutants
0        8809  {"a": "46", "b": "3", "c": "12"}
1        8810   {"a": "36", "b": "5", "c": "8"}
2        8811              {"b": "2", "c": "7"}
3        8812                       {"c": "11"}
4        8813            {"a": "82", "c": "15"}
5        8814                               NaN
# check the type of the first value in Pollutants
>>> print(type(df.iloc[0, 1]))
<class 'str'>
# replace NaN with '{}' if the column is strings, otherwise replace with {}
df.Pollutants = df.Pollutants.fillna('{}')  # if the NaN is in a column of strings
# df.Pollutants = df.Pollutants.fillna({i: {} for i in df.index})  # if the column is not strings
# Convert the column of stringified dicts to dicts
# skip this line, if the column contains dicts
df.Pollutants = df.Pollutants.apply(literal_eval)
# reset the index if the index is not unique integers from 0 to n-1
# df.reset_index(inplace=True)  # uncomment if needed
# remove and normalize the column of dictionaries, and join the result to df
df = df.join(pd.json_normalize(df.pop('Pollutants')))
# display(df)
   Station ID    a    b    c
0        8809   46    3   12
1        8810   36    5    8
2        8811  NaN    2    7
3        8812  NaN  NaN   11
4        8813   82  NaN   15
5        8814  NaN  NaN  NaN
%%timeit
 
# dataframe with 1M rows
dfb = pd.concat([df]*20000).reset_index(drop=True)
%%timeit
dfb.join(pd.json_normalize(dfb.Pollutants))
[out]:
46.9 ms ± 201 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
pd.concat([dfb.drop(columns=['Pollutants']), dfb.Pollutants.apply(pd.Series)], axis=1)
[out]:
7.75 s ± 52.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
이것을 시험해 보세요.SQL에서 반환되는 데이터는 딕트로 변환되어야 합니다.아니면 그럴 수도 있고"Pollutant Levels" is금 is is이다Pollutants'
   StationID                   Pollutants
0       8809  {"a":"46","b":"3","c":"12"}
1       8810   {"a":"36","b":"5","c":"8"}
2       8811            {"b":"2","c":"7"}
3       8812                   {"c":"11"}
4       8813          {"a":"82","c":"15"}
df2["Pollutants"] = df2["Pollutants"].apply(lambda x : dict(eval(x)) )
df3 = df2["Pollutants"].apply(pd.Series )
    a    b   c
0   46    3  12
1   36    5   8
2  NaN    2   7
3  NaN  NaN  11
4   82  NaN  15
result = pd.concat([df, df3], axis=1).drop('Pollutants', axis=1)
result
   StationID    a    b   c
0       8809   46    3  12
1       8810   36    5   8
2       8811  NaN    2   7
3       8812  NaN  NaN  11
4       8813   82  NaN  15
'공해제' 열을 추출하는 방법을 적극 권장합니다.
df_pollutants = pd.DataFrame(df['Pollutants'].values.tolist(), index=df.index)
보다 훨씬 빠르다
df_pollutants = df['Pollutants'].apply(pd.Series)
df의 크기가 클 때.
멀린의 답변이 더 좋고 아주 쉽지만 람다 함수는 필요 없습니다.사전 평가는 아래 그림과 같이 다음 두 가지 방법 중 하나로 무시해도 됩니다.
방법 1: 2단계
# step 1: convert the `Pollutants` column to Pandas dataframe series
df_pol_ps = data_df['Pollutants'].apply(pd.Series)
df_pol_ps:
    a   b   c
0   46  3   12
1   36  5   8
2   NaN 2   7
3   NaN NaN 11
4   82  NaN 15
# step 2: concat columns `a, b, c` and drop/remove the `Pollutants` 
df_final = pd.concat([df, df_pol_ps], axis = 1).drop('Pollutants', axis = 1)
df_final:
    StationID   a   b   c
0   8809    46  3   12
1   8810    36  5   8
2   8811    NaN 2   7
3   8812    NaN NaN 11
4   8813    82  NaN 15
방법 2: 위의 두 단계를 한 번에 결합할 수 있습니다.
df_final = pd.concat([df, df['Pollutants'].apply(pd.Series)], axis = 1).drop('Pollutants', axis = 1)
df_final:
    StationID   a   b   c
0   8809    46  3   12
1   8810    36  5   8
2   8811    NaN 2   7
3   8812    NaN NaN 11
4   8813    82  NaN 15
판다와 함께 사전 열을 다른 열로 분할하려면 어떻게 해야 합니까?
pd.DataFrame(df['val'].tolist())는 사전 입니다.
 
여기 컬러풀한 그래프를 사용한 당신의 증거가 있습니다.
참조용 벤치마크 코드.
하는 데 인 결과(예를 , ''을 이기 때문에 을 재는 결과 구성의 다른 측면(사용 여부입니다.pop ★★★★★★★★★★★★★★★★★」drop에 무시할 수 단, 를 사용하는 ).pop 조치를 drop만, 해, 「」을 「Call」로 .pd.DataFrame( 쪽쪽이 ( )
 ★★★★★pop는 입력 DataFrame을 파괴적으로 변환하기 때문에 벤치마크 코드에서 실행하기가 더 어려워집니다. 벤치마크 코드는 테스트 실행 중에도 입력이 변경되지 않는다고 가정합니다.
기타 솔루션에 대한 비판
- df['val'].apply(pd.Series)팬더가 각 열에 대해 Series 개체를 구성한 후 이 개체에서 DataFrame을 구축하기 때문에 대형 N의 경우 속도가 매우 느립니다.N이 클수록 퍼포먼스는 분 단위 또는 시간 단위로 저하됩니다.
- pd.json_normalize(df['val']))is다- json_normalize는 훨씬 더 복잡한 입력 데이터(특히 여러 레코드 경로와 메타데이터가 포함된 깊이 중첩된 JSON)를 사용하는 것을 목적으로 합니다. .- pd.DataFrame이 정도면 충분하니까 받아쓰기가 밋밋할 때 쓰세요.
- 은 '그러다'를 제시하기도 합니다. - df.pop('val').values.tolist()★★★★★★★★★★★★★★★★★」- df.pop('val').to_numpy().tolist()시리즈를 나열하든 numpy 배열이든 큰 차이는 없다고 생각합니다.시리즈를 직접 나열하는 작업이 하나 적고 실제로 속도가 느리지 않으므로 중간 단계에서 numpy 어레이를 생성하지 않는 것이 좋습니다.
참고: 깊이=1인 사전의 경우(단일 수준)
>>> df
   Station ID                        Pollutants
0        8809  {"a": "46", "b": "3", "c": "12"}
1        8810   {"a": "36", "b": "5", "c": "8"}
2        8811              {"b": "2", "c": "7"}
3        8812                       {"c": "11"}
4        8813            {"a": "82", "c": "15"}
1,000만 행의 대규모 데이터 세트에 대한 속도 비교
>>> df = pd.concat([df]*2000000).reset_index(drop=True)
>>> print(df.shape)
(10000000, 2)
def apply_drop(df):
    return df.join(df['Pollutants'].apply(pd.Series)).drop('Pollutants', axis=1)  
def json_normalise_drop(df):
    return df.join(pd.json_normalize(df.Pollutants)).drop('Pollutants', axis=1)  
def tolist_drop(df):
    return df.join(pd.DataFrame(df['Pollutants'].tolist())).drop('Pollutants', axis=1)  
def vlues_tolist_drop(df):
    return df.join(pd.DataFrame(df['Pollutants'].values.tolist())).drop('Pollutants', axis=1)  
def pop_tolist(df):
    return df.join(pd.DataFrame(df.pop('Pollutants').tolist()))  
def pop_values_tolist(df):
    return df.join(pd.DataFrame(df.pop('Pollutants').values.tolist()))
>>> %timeit apply_drop(df.copy())
1 loop, best of 3: 53min 20s per loop
>>> %timeit json_normalise_drop(df.copy())
1 loop, best of 3: 54.9 s per loop
>>> %timeit tolist_drop(df.copy())
1 loop, best of 3: 6.62 s per loop
>>> %timeit vlues_tolist_drop(df.copy())
1 loop, best of 3: 6.63 s per loop
>>> %timeit pop_tolist(df.copy())
1 loop, best of 3: 5.99 s per loop
>>> %timeit pop_values_tolist(df.copy())
1 loop, best of 3: 5.94 s per loop
+---------------------+-----------+
| apply_drop          | 53min 20s |
| json_normalise_drop |    54.9 s |
| tolist_drop         |    6.62 s |
| vlues_tolist_drop   |    6.63 s |
| pop_tolist          |    5.99 s |
| pop_values_tolist   |    5.94 s |
+---------------------+-----------+
df.join(pd.DataFrame(df.pop('Pollutants').values.tolist()))가장 빠르다
하시면 됩니다.joinpop+tolist퍼포먼스는 다음 제품과 동등합니다.concatdrop+tolist구문을  수 
res = df.join(pd.DataFrame(df.pop('b').tolist()))
다른 방법을 사용한 벤치마킹:
df = pd.DataFrame({'a':[1,2,3], 'b':[{'c':1}, {'d':3}, {'c':5, 'd':6}]})
def joris1(df):
    return pd.concat([df.drop('b', axis=1), df['b'].apply(pd.Series)], axis=1)
def joris2(df):
    return pd.concat([df.drop('b', axis=1), pd.DataFrame(df['b'].tolist())], axis=1)
def jpp(df):
    return df.join(pd.DataFrame(df.pop('b').tolist()))
df = pd.concat([df]*1000, ignore_index=True)
%timeit joris1(df.copy())  # 1.33 s per loop
%timeit joris2(df.copy())  # 7.42 ms per loop
%timeit jpp(df.copy())     # 7.68 ms per loop
다음과 같은 한 가지 솔루션이 있습니다.
>>> df = pd.concat([df['Station ID'], df['Pollutants'].apply(pd.Series)], axis=1)
>>> print(df)
   Station ID    a    b   c
0        8809   46    3  12
1        8810   36    5   8
2        8811  NaN    2   7
3        8812  NaN  NaN  11
4        8813   82  NaN  15
df = pd.concat([df['a'], df.b.apply(pd.Series)], axis=1)
이러한 단계를 메서드로 연결했습니다. 데이터 프레임과 확장 명령어가 포함된 열만 전달하면 됩니다.
def expand_dataframe(dw: pd.DataFrame, column_to_expand: str) -> pd.DataFrame:
    """
    dw: DataFrame with some column which contain a dict to expand
        in columns
    column_to_expand: String with column name of dw
    """
    import pandas as pd
    def convert_to_dict(sequence: str) -> Dict:
        import json
        s = sequence
        json_acceptable_string = s.replace("'", "\"")
        d = json.loads(json_acceptable_string)
        return d    
    expanded_dataframe = pd.concat([dw.drop([column_to_expand], axis=1),
                                    dw[column_to_expand]
                                    .apply(convert_to_dict)
                                    .apply(pd.Series)],
                                    axis=1)
    return expanded_dataframe
my_df = pd.DataFrame.from_dict(my_dict, orient='index', columns=['my_col'])
..dict를 적절히 해석하여(각 dict 키를 별도의 df 열에, 키 값을 df 행에 포함), 처음부터 dict가 단일 열에 압축되지 않도록 합니다.
언급URL : https://stackoverflow.com/questions/38231591/split-explode-a-column-of-dictionaries-into-separate-columns-with-pandas
'sourcecode' 카테고리의 다른 글
| 두 시스템 간의 연결 및 인스턴스 이동 (0) | 2023.01.15 | 
|---|---|
| angularjs(1.x)를 사용하여 HTML 요소의 id 속성을 동적으로 설정하려면 어떻게 해야 합니까? (0) | 2023.01.15 | 
| Tomcat의 루트에 응용 프로그램 배포 (0) | 2023.01.15 | 
| 현재 버전의 MySQL 데이터베이스 관리 시스템(DBMS)을 검색하려면 어떻게 해야 합니까? (0) | 2023.01.15 | 
| XAMPP에서 MariaDB를 MySQL로 변경하려면 어떻게 해야 하나요? (0) | 2023.01.15 | 
