사전 목록을 팬더 DataFrame으로 변환


656

다음과 같은 사전 목록이 있습니다.

[{'points': 50, 'time': '5:00', 'year': 2010}, 
{'points': 25, 'time': '6:00', 'month': "february"}, 
{'points':90, 'time': '9:00', 'month': 'january'}, 
{'points_h1':20, 'month': 'june'}]

그리고 나는 이것을 이렇게 팬더로 바꾸고 DataFrame싶습니다.

      month  points  points_h1  time  year
0       NaN      50        NaN  5:00  2010
1  february      25        NaN  6:00   NaN
2   january      90        NaN  9:00   NaN
3      june     NaN         20   NaN   NaN

참고 : 열 순서는 중요하지 않습니다.

위와 같이 사전 목록을 팬더 DataFrame으로 바꾸려면 어떻게해야합니까?

답변:


950

치죠는 d단순히 dicts의 목록입니다 :

pd.DataFrame(d)

3
키 / 값 쌍 중 하나를 인덱스 (예 : 시간)로 어떻게 사용할 수 있습니까?
CatsLoveJazz

6
@CatsLoveJazz 당신은 df = df.set_index('time')나중에 할 수 있습니다
joris

1
@CatsLoveJazz 아니요, dict에서 변환 할 때는 불가능합니다.
joris

6
Pandas 0.19.2부터는 문서에 적어도 이것에 대한 언급이 없습니다.pandas.DataFrame
Leo Alekseyev

1
중첩 된 사전의 '{"":{"...경우 json_normalize 접근법을 사용한다는 점에 유의하십시오. @ cs95
Lorenz

136

사전 목록을 pandas DataFrame으로 어떻게 변환합니까?

다른 답변은 정확하지만 이러한 방법의 장점과 한계에 대해서는별로 설명되지 않았습니다. 이 게시물의 목적은 다양한 상황에서 이러한 방법의 예를 보여주고 사용시기 (및 사용하지 않을시기)를 논의하고 대안을 제안하는 것입니다.


DataFrame(), DataFrame.from_records().from_dict()

데이터의 구조와 형식에 따라 세 가지 방법이 모두 작동하거나 일부 방법이 다른 방법보다 잘 작동하거나 전혀 작동하지 않는 상황이 있습니다.

매우 고안된 예를 고려하십시오.

np.random.seed(0)
data = pd.DataFrame(
    np.random.choice(10, (3, 4)), columns=list('ABCD')).to_dict('r')

print(data)
[{'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]

이 목록은 모든 키가있는 "레코드"로 구성됩니다. 가장 간단한 경우입니다.

# The following methods all produce the same output.
pd.DataFrame(data)
pd.DataFrame.from_dict(data)
pd.DataFrame.from_records(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

사전 오리엔테이션에 대한 단어 : orient='index'/'columns'

계속하기 전에 다른 유형의 사전 방향을 구별하고 팬더를 지원하는 것이 중요합니다. "열"과 "인덱스"의 두 가지 기본 유형이 있습니다.

orient='columns'
"열"방향의 사전은 해당 키가 해당 DataFrame의 열에 해당합니다.

예를 들어, data위는 "열"방향입니다.

data_c = [
 {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 {'A': 2, 'B': 4, 'C': 7, 'D': 6}]

pd.DataFrame.from_dict(data_c, orient='columns')

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

참고 :를 사용하는 경우 pd.DataFrame.from_records방향은 "열"인 것으로 가정하고 (달리 지정할 수 없음) 사전이 그에 따라로드됩니다.

orient='index'
이 방향으로 키는 색인 값에 해당하는 것으로 가정합니다. 이러한 종류의 데이터는에 가장 적합합니다 pd.DataFrame.from_dict.

data_i ={
 0: {'A': 5, 'B': 0, 'C': 3, 'D': 3},
 1: {'A': 7, 'B': 9, 'C': 3, 'D': 5},
 2: {'A': 2, 'B': 4, 'C': 7, 'D': 6}}

pd.DataFrame.from_dict(data_i, orient='index')

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

이 사례는 OP에서 고려되지는 않지만 여전히 유용합니다.

맞춤 색인 설정

결과 DataFrame에 사용자 정의 색인이 필요한 경우 index=...인수를 사용하여 설정할 수 있습니다 .

pd.DataFrame(data, index=['a', 'b', 'c'])
# pd.DataFrame.from_records(data, index=['a', 'b', 'c'])

   A  B  C  D
a  5  0  3  3
b  7  9  3  5
c  2  4  7  6

에서 지원하지 않습니다 pd.DataFrame.from_dict.

누락 된 키 / 열 다루기

누락 된 키 / 열 값이있는 사전을 처리 할 때 모든 방법이 기본적으로 작동합니다. 예를 들어

data2 = [
     {'A': 5, 'C': 3, 'D': 3},
     {'A': 7, 'B': 9, 'F': 5},
     {'B': 4, 'C': 7, 'E': 6}]

# The methods below all produce the same output.
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)

     A    B    C    D    E    F
0  5.0  NaN  3.0  3.0  NaN  NaN
1  7.0  9.0  NaN  NaN  NaN  5.0
2  NaN  4.0  7.0  NaN  6.0  NaN

열의 하위 집합 읽기

"모든 열에서 읽지 않으려면 어떻게합니까?" columns=...매개 변수를 사용하여이를 쉽게 지정할 수 있습니다 .

예를 들어, data2위 의 예제 사전에서 "A", 'D'및 'F'열만 읽으려면 목록을 전달하면됩니다.

pd.DataFrame(data2, columns=['A', 'D', 'F'])
# pd.DataFrame.from_records(data2, columns=['A', 'D', 'F'])

     A    D    F
0  5.0  3.0  NaN
1  7.0  NaN  5.0
2  NaN  NaN  NaN

pd.DataFrame.from_dict기본 방향 "열" 에서는 지원되지 않습니다 .

pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])

ValueError: cannot use columns parameter with orient='columns'

행의 하위 집합 읽기

이러한 방법 중 어느 것도 직접 지원하지 않습니다 . 반복 할 때 데이터를 반복하여 전체 삭제 를 수행해야합니다 . 예를 들어, 위에서 0 번째 와 2 번째 행만 추출 data2하려면 다음을 사용할 수 있습니다.

rows_to_select = {0, 2}
for i in reversed(range(len(data2))):
    if i not in rows_to_select:
        del data2[i]

pd.DataFrame(data2)
# pd.DataFrame.from_dict(data2)
# pd.DataFrame.from_records(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

만병 통치약 : json_normalize 중첩 데이터

위에서 설명한 방법에 대한 강력하고 강력한 대안 json_normalize은 사전 (레코드) 목록과 함께 작동 하는 기능이며 중첩 된 사전도 처리 할 수 ​​있습니다.

pd.io.json.json_normalize(data)

   A  B  C  D
0  5  0  3  3
1  7  9  3  5
2  2  4  7  6

pd.io.json.json_normalize(data2)

     A    B  C    D    E
0  5.0  NaN  3  3.0  NaN
1  NaN  4.0  7  NaN  6.0

다시 전달 된 데이터는 json_normalize사전 목록 (레코드) 형식이어야합니다.

언급 한 바와 같이 json_normalize중첩 된 사전도 처리 할 수 ​​있습니다. 다음은 문서에서 가져온 예입니다.

data_nested = [
  {'counties': [{'name': 'Dade', 'population': 12345},
                {'name': 'Broward', 'population': 40000},
                {'name': 'Palm Beach', 'population': 60000}],
   'info': {'governor': 'Rick Scott'},
   'shortname': 'FL',
   'state': 'Florida'},
  {'counties': [{'name': 'Summit', 'population': 1234},
                {'name': 'Cuyahoga', 'population': 1337}],
   'info': {'governor': 'John Kasich'},
   'shortname': 'OH',
   'state': 'Ohio'}
]

pd.io.json.json_normalize(data_nested, 
                          record_path='counties', 
                          meta=['state', 'shortname', ['info', 'governor']])

         name  population    state shortname info.governor
0        Dade       12345  Florida        FL    Rick Scott
1     Broward       40000  Florida        FL    Rick Scott
2  Palm Beach       60000  Florida        FL    Rick Scott
3      Summit        1234     Ohio        OH   John Kasich
4    Cuyahoga        1337     Ohio        OH   John Kasich

metarecord_path인수 에 대한 자세한 내용 은 설명서를 확인하십시오.


요약

지원되는 특징 / 기능과 함께 위에서 설명한 모든 방법에 대한 표가 있습니다.

여기에 이미지 설명을 입력하십시오

*를 사용한 orient='columns'다음 조옮김과 같은 효과를 얻습니다 orient='index'.


8
우와! 좋아, SO 게시물 병합 과 함께 API에 속합니다. 아직 팬더 문서를 작성하지 않은 경우 문서에 기여해야합니다. 테드 페트로 우 (Ted Petrou) 는 스택 오버플로에서 팬더의 인기에 대한 링크드 인 기사를 올렸으며 여기에 좋은 문서가 부족하면 여기에 많은 양의 질문에 기여한다고 언급했습니다.
Scott Boston

2
@ScottBoston 당신은 절대적으로 옳습니다. 나는 그것이 더 진지한 생각을해야만한다는 것을 지금은 충분히 알고 있습니다. 필자는이 문서가 동일한 대상의 일부에 해당하는 질문에 게시하는 것보다 사용자를 돕는 훌륭한 방법이라고 생각합니다.
cs95

1
그것은 좋은 대답입니다, 나는 우리가 가장 최근의 판다 버전에서 일반적인 질문에 다시 걸어야 할 때라고 생각합니다 :-)
YOBEN_S

3
@ely : 그것은 어쨌든 여기에 답을 쓰지 않는 이유가 아닙니다 . 모든 답변은 구식이 될 수 있고, 우리가 투표 한 내용이며, 여기에는 다른 관점과 다른 목표가 있으며, 항상 같은 것을 설명하는 다른 방법을 갖는 것이 중요합니다.
Martijn Pieters

1
@MartijnPieters 마지막 어설 션에 의문을 제기하고 동의하지 않지만 전반적으로 동의합니다. 동일한 답변에 대해 서로 다른 답변을한데 모으는 것이 항상 가치있는 것은 아닙니다. 특히 일부 답변이 다른 답변에 따라 업데이트되거나 조건부 차이가있는 경우에 특히 그렇습니다. 최악의 경우, 이러한 답변은 함께 정렬 될 때 가치를 떨어 뜨릴 수 있습니다 (더 오래된 답변을보다 정확한 상태로 편집하기 위해 더 업데이트 된 답변을 사용하는 것과 대조적으로). 그러나 다시, 나는 당신에게 크게 동의합니다.
ely

83

팬더 16.2에서는 pd.DataFrame.from_records(d)이것을 작동시키기 위해해야했습니다.


1
이 접근 방식의 장점은 다음과 같이 작동한다는 것입니다.deque
MBZ

3
0.17.1@joris 솔루션 으로 팬더 와 잘 작동
Anton Protopopov

2
Usinig 0.14.1 및 @joris '솔루션은 작동하지 않았지만 이것은 작동했습니다
mchen

13
에서은 0.18.1, 하나는 사용해야합니다 from_records사전의 모든 동일한 키가없는 경우.
fredcallaway

23

다음 pd.DataFrame.from_dict(d)과 같이 사용할 수도 있습니다 .

In [8]: d = [{'points': 50, 'time': '5:00', 'year': 2010}, 
   ...: {'points': 25, 'time': '6:00', 'month': "february"}, 
   ...: {'points':90, 'time': '9:00', 'month': 'january'}, 
   ...: {'points_h1':20, 'month': 'june'}]

In [12]: pd.DataFrame.from_dict(d)
Out[12]: 
      month  points  points_h1  time    year
0       NaN    50.0        NaN  5:00  2010.0
1  february    25.0        NaN  6:00     NaN
2   january    90.0        NaN  9:00     NaN
3      june     NaN       20.0   NaN     NaN

문제는에서 데이터 프레임을 구성에 관한 목록dict하지 단일에서의 dict당신이 당신의 대답에 가정한다.
a_guest

@a_guest 업데이트 된 답변을 확인하십시오. 나는 가정하지 않습니다.
shivsn

2

나는 몇몇 사람들이 이것을 발견하고 여기서 도움이되는 것을 찾지 못한다는 것을 알고 있습니다. 내가 찾은 가장 쉬운 방법은 다음과 같습니다.

dict_count = len(dict_list)
df = pd.DataFrame(dict_list[0], index=[0])
for i in range(1,dict_count-1):
    df = df.append(dict_list[i], ignore_index=True)

이것이 누군가를 돕기를 바랍니다!


1
list=[{'points': 50, 'time': '5:00', 'year': 2010}, 
{'points': 25, 'time': '6:00', 'month': "february"}, 
{'points':90, 'time': '9:00', 'month': 'january'}, 
{'points_h1':20, 'month': 'june'}]

간단한 전화 :

pd=DataFrame.from_dict(list, orient='columns', dtype=None)

print(pd)

0

Pyhton3 : 이전에 나열된 대부분의 솔루션이 작동합니다. 그러나 데이터 프레임의 row_number가 필요하지 않고 각 행 (레코드)을 개별적으로 작성해야하는 경우가 있습니다.

이 경우 다음 방법이 유용합니다.

import csv

my file= 'C:\Users\John\Desktop\export_dataframe.csv'

records_to_save = data2 #used as in the thread. 


colnames = list[records_to_save[0].keys()] 
# remember colnames is a list of all keys. All values are written corresponding
# to the keys and "None" is specified in case of missing value 

with open(myfile, 'w', newline="",encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(colnames)
    for d in records_to_save:
        writer.writerow([d.get(r, "None") for r in colnames])

0

사전 목록을 pandas DataFrame으로 변환하려면 "append"를 사용할 수 있습니다.

우리는이라는 사전 dic및 DIC 30 개 목록 항목이 ( list1, list2, ..., list30)

  1. 1 단계 : 당신의 결과를 유지하기위한 변수를 정의 (예를 : total_df)
  2. 2 단계 : 초기화 total_dflist1
  3. step3 : 모든 목록을 추가하려면 "for loop"를 사용하십시오. total_df
total_df=list1
nums=Series(np.arange(start=2, stop=31))
for num in nums:
    total_df=total_df.append(dic['list'+str(num)])

가에 대한 상세한 두 살짜리 대답 @ cs95에 의해 설명 된 접근 방법을 통해이 방법의 장점은 무엇입니까 DataFrame(), DataFrame.from_records()그리고 .from_dict()?
Jeremy Caney

30 가지 목록이있는 사전에 대해 위의 모든 방법을 테스트했지만 Append 함수를 사용하여 답을 얻었습니다.
Armin Ahmadi Nasab
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.