열에서 여러 데이터 프레임을 결합하는 팬더 3 방향


191

CSV 파일이 3 개 있습니다. 각각은 사람의 (문자열) 이름으로 첫 번째 열을 갖는 반면, 각 데이터 프레임의 다른 모든 열은 해당 개인의 속성입니다.

세 개의 CSV 문서를 모두 "결합"하여 각 행에 개인 문자열 이름의 각 고유 값에 대한 모든 속성이있는 단일 CSV를 만들려면 어떻게해야합니까?

join()pandas 의 함수는 다중 인덱스가 필요하다는 것을 지정하지만 단일 인덱스를 기반으로 조인을 만드는 것과 계층 적 인덱싱 체계가 무엇을 해야하는지 혼란 스럽습니다.


2
다중 색인이 필요하지 않습니다. 조인 문서에서 조인 할 여러 열을 전달할 때 다중 인덱스가 없으므로 처리합니다.
cwharland

1
내 시험에서 df1.join([df2, df3], on=[df2_col1, df3_col1])작동하지 않았다.
lollercoaster

주어진 답변에서와 같이 그것들을 묶어야합니다. 병합 DF1 및 DF2는 DF3과 결과를 병합
cwharland

답변:


474

가정 수입 :

import pandas as pd

John Galt의 대답 은 기본적으로 reduce작업입니다. 소수의 데이터 프레임이있는 경우 다음과 같은 목록에 추가합니다 (목록 이해 또는 루프 또는 기타를 통해 생성됨).

dfs = [df0, df1, df2, dfN]

name예 와 같이 공통 열이 있다고 가정하면 다음을 수행합니다.

df_final = reduce(lambda left,right: pd.merge(left,right,on='name'), dfs)

이런 식으로 코드는 병합하려는 데이터 프레임 수에 관계없이 작동해야합니다.

2016 년 8 월 1 일 수정 : Python 3을 사용하는 사람들 reduce은로 이동했습니다 functools. 따라서이 기능을 사용하려면 먼저 해당 모듈을 가져와야합니다.

from functools import reduce

11
방금 이것을 사용해 reducefunctools.reduceimport functools functools.reduce(.......)
보았는데

3
가입 할 필드 이름이 다른 경우이 솔루션은 어떻게 작동합니까? 예를 들어, 세 개의 데이터 프레임에 내가 가질 수 name1, name2name3각각.
ps0604

2
이것은 우리가 n-1merge 함수를 호출 한다는 것을 의미하지 않습니까? 이 경우 데이터 프레임 수가 적은 경우에는 중요하지 않지만 더 확장 가능한 솔루션이 있는지 궁금합니다.
eapolinario 2016 년

1
이것은 df열 다중 인덱스가있는 내 경우에는 효과가 없었습니다 (첫 번째 병합에서 작동하는 열로 'on'을 주입했지만 후속 병합은 실패했습니다). 대신 다음과 같이 작동합니다.df = reduce(lambda left, right: left.join(right, how='outer', on='Date'), dfs)
Adrian Torrie

+1 ~ ps0604. 조인 열이 다르면 어떻게 작동합니까? 조인 열이 다른 경우 pd.merge를 사용해야합니까? 감사
스티브

106

3 개의 데이터 프레임이 있으면 시도해 볼 수 있습니다

# Merge multiple dataframes
df1 = pd.DataFrame(np.array([
    ['a', 5, 9],
    ['b', 4, 61],
    ['c', 24, 9]]),
    columns=['name', 'attr11', 'attr12'])
df2 = pd.DataFrame(np.array([
    ['a', 5, 19],
    ['b', 14, 16],
    ['c', 4, 9]]),
    columns=['name', 'attr21', 'attr22'])
df3 = pd.DataFrame(np.array([
    ['a', 15, 49],
    ['b', 4, 36],
    ['c', 14, 9]]),
    columns=['name', 'attr31', 'attr32'])

pd.merge(pd.merge(df1,df2,on='name'),df3,on='name')

또는 cwharland가 언급 한 바와 같이

df1.merge(df2,on='name').merge(df3,on='name')

34
청소기 외모를 들어 당신이 그들을 체인 수 df1.merge(df2,on='name').merge(df3,on='name')
cwharland

1
가입 할 필드 이름이 다른 경우이 솔루션은 어떻게 작동합니까? 예를 들어, 세 개의 데이터 프레임에 내가 가질 수있다 name1, name2그리고 name3각각
ps0604을

4
@ ps0604df1.merge(df2,left_on='name1', right_on='name2').merge(df3,left_on='name1', right_on='name3').drop(columns=['name2', 'name3']).rename(columns={'name1':'name'})
Michael H.

또한 인덱스를 사용 하여이 작업을 수행하는 방법. 'name'이 (가) 인덱스이고 열 이름이 아닌 경우 작동하지 않는 것 같습니다.
Brian D

85

join방법 의 이상적인 상황입니다

join방법은 이러한 유형의 상황에 맞게 작성되었습니다. 원하는 수의 DataFrame을 함께 결합 할 수 있습니다. 호출하는 DataFrame은 전달 된 DataFrame 컬렉션의 인덱스와 결합됩니다. 여러 DataFrame을 사용하려면 조인 열을 인덱스에 넣어야합니다.

코드는 다음과 같습니다.

filenames = ['fn1', 'fn2', 'fn3', 'fn4',....]
dfs = [pd.read_csv(filename, index_col=index_col) for filename in filenames)]
dfs[0].join(dfs[1:])

@zero의 데이터를 사용하면 다음과 같이 할 수 있습니다.

df1 = pd.DataFrame(np.array([
    ['a', 5, 9],
    ['b', 4, 61],
    ['c', 24, 9]]),
    columns=['name', 'attr11', 'attr12'])
df2 = pd.DataFrame(np.array([
    ['a', 5, 19],
    ['b', 14, 16],
    ['c', 4, 9]]),
    columns=['name', 'attr21', 'attr22'])
df3 = pd.DataFrame(np.array([
    ['a', 15, 49],
    ['b', 4, 36],
    ['c', 14, 9]]),
    columns=['name', 'attr31', 'attr32'])

dfs = [df1, df2, df3]
dfs = [df.set_index('name') for df in dfs]
dfs[0].join(dfs[1:])

     attr11 attr12 attr21 attr22 attr31 attr32
name                                          
a         5      9      5     19     15     49
b         4     61     14     16      4     36
c        24      9      4      9     14      9

4
모든 df를 빈 데이터 프레임에 결합하면 다음과 같이 작동합니다 pd.DataFrame().join(dfs, how="outer"). 일부 상황에서는 더 깨끗할 수 있습니다.
Dominik

4
이것은 괜찮은 조언이며 이제 101을 병합 하는 팬더에 통합 되었습니다 (여러 데이터 프레임 병합에 대한 섹션 참조). 조인 키가 고유 한 경우를 사용 pd.concat하면 구문이 더 단순 해 pd.concat([df.set_index('name') for df in dfs], axis=1, join='inner').reset_index()집니다. 내부 또는 외부 조인 만 수행 할 수는 있지만 concat여러 df에서 중복 열 이름을 처리 할 때 더 유용합니다 ( join이것은 좋지 않습니다).
cs95

dfs[0].join(dfs[1:])dfs[0].join(dfs[1:], sort=False) 그렇지 FutureWarning않으면가 팝업 되기 때문에에 수정해야 합니다. 좋은 예를 주셔서 감사합니다.
gies0r

: 그 시도에 오류가 ValueError: Indexes have overlapping values목록에서 개별 dataframes 검사하여, 그들이 중복 값이하지 않는 것,하지만.
SomJura

17

데이터 프레임 목록에 대해 다음과 같이 수행 할 수도 있습니다 df_list.

df = df_list[0]
for df_ in df_list[1:]:
    df = df.merge(df_, on='join_col_name')

또는 데이터 프레임이 생성기 객체에있는 경우 (예 : 메모리 소비를 줄이기 위해) :

df = next(df_list)
for df_ in df_list:
    df = df.merge(df_, on='join_col_name')

11

0.22.0의 python3.6.3 에서는 결합에 사용하려는 열을 색인으로 설정 pandas하는 한 사용할 수도 있습니다.concat

pd.concat(
    (iDF.set_index('name') for iDF in [df1, df2, df3]),
    axis=1, join='inner'
).reset_index()

어디에서 df1, df2그리고 df3같이 정의된다 존 갈트의 대답

import pandas as pd
df1 = pd.DataFrame(np.array([
    ['a', 5, 9],
    ['b', 4, 61],
    ['c', 24, 9]]),
    columns=['name', 'attr11', 'attr12']
)
df2 = pd.DataFrame(np.array([
    ['a', 5, 19],
    ['b', 14, 16],
    ['c', 4, 9]]),
    columns=['name', 'attr21', 'attr22']
)
df3 = pd.DataFrame(np.array([
    ['a', 15, 49],
    ['b', 4, 36],
    ['c', 14, 9]]),
    columns=['name', 'attr31', 'attr32']
)

2
이것이 정답입니다. 가장 빠릅니다.
R. Zhu

4

조인 작업 을 수행하기 위해 다중 인덱스가 필요하지 않습니다 . 조인 작업을 수행 할 인덱스 열을 올바르게 설정하면됩니다 ( df.set_index('Name')예 : 명령 )

join작업은 인덱스에서 수행 기본입니다. 귀하의 경우, Name열이 색인과 일치하도록 지정해야합니다 . 아래는 예입니다

튜토리얼 유용 할 수 있습니다.

# Simple example where dataframes index are the name on which to perform the join operations
import pandas as pd
import numpy as np
name = ['Sophia' ,'Emma' ,'Isabella' ,'Olivia' ,'Ava' ,'Emily' ,'Abigail' ,'Mia']
df1 = pd.DataFrame(np.random.randn(8, 3), columns=['A','B','C'], index=name)
df2 = pd.DataFrame(np.random.randn(8, 1), columns=['D'],         index=name)
df3 = pd.DataFrame(np.random.randn(8, 2), columns=['E','F'],     index=name)
df = df1.join(df2)
df = df.join(df3)

# If you a 'Name' column that is not the index of your dataframe, one can set this column to be the index
# 1) Create a column 'Name' based on the previous index
df1['Name']=df1.index
# 1) Select the index from column 'Name'
df1=df1.set_index('Name')

# If indexes are different, one may have to play with parameter how
gf1 = pd.DataFrame(np.random.randn(8, 3), columns=['A','B','C'], index=range(8))
gf2 = pd.DataFrame(np.random.randn(8, 1), columns=['D'], index=range(2,10))
gf3 = pd.DataFrame(np.random.randn(8, 2), columns=['E','F'], index=range(4,12))

gf = gf1.join(gf2, how='outer')
gf = gf.join(gf3, how='outer')

4

다음은 열 이름을 사전과 동기화하면서 데이터 프레임 사전을 병합하는 방법입니다. 또한 필요한 경우 결 측값을 채 웁니다.

이것은 데이터 프레임의 사전을 병합하는 기능입니다

def MergeDfDict(dfDict, onCols, how='outer', naFill=None):
  keys = dfDict.keys()
  for i in range(len(keys)):
    key = keys[i]
    df0 = dfDict[key]
    cols = list(df0.columns)
    valueCols = list(filter(lambda x: x not in (onCols), cols))
    df0 = df0[onCols + valueCols]
    df0.columns = onCols + [(s + '_' + key) for s in valueCols] 

    if (i == 0):
      outDf = df0
    else:
      outDf = pd.merge(outDf, df0, how=how, on=onCols)   

  if (naFill != None):
    outDf = outDf.fillna(naFill)

  return(outDf)

좋아, 데이터를 생성하고 이것을 테스트하자 :

def GenDf(size):
  df = pd.DataFrame({'categ1':np.random.choice(a=['a', 'b', 'c', 'd', 'e'], size=size, replace=True),
                      'categ2':np.random.choice(a=['A', 'B'], size=size, replace=True), 
                      'col1':np.random.uniform(low=0.0, high=100.0, size=size), 
                      'col2':np.random.uniform(low=0.0, high=100.0, size=size)
                      })
  df = df.sort_values(['categ2', 'categ1', 'col1', 'col2'])
  return(df)


size = 5
dfDict = {'US':GenDf(size), 'IN':GenDf(size), 'GER':GenDf(size)}   
MergeDfDict(dfDict=dfDict, onCols=['categ1', 'categ2'], how='outer', naFill=0)

3

간단한 해결책 :

열 이름이 비슷한 경우 :

 df1.merge(df2,on='col_name').merge(df3,on='col_name')

열 이름이 다른 경우 :

df1.merge(df2,left_on='col_name1', right_on='col_name2').merge(df3,left_on='col_name1', right_on='col_name3').drop(columns=['col_name2', 'col_name3']).rename(columns={'col_name1':'col_name'})

2

팬더 문서의 다른 솔루션이 있습니다 (여기서는 보이지 않습니다).

사용하여 .append

>>> df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
   A  B
0  1  2
1  3  4
>>> df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
   A  B
0  5  6
1  7  8
>>> df.append(df2, ignore_index=True)
   A  B
0  1  2
1  3  4
2  5  6
3  7  8

ignore_index=True소스 하나 가능한 다음의 인덱스로 대체 첨부 dataframe의 인덱스를 무시하는데 사용된다.

다른 열 이름 Nan이 있으면 소개됩니다.


누군가 "join"이라는 단어를 사용하여 두 개의 데이터 프레임을 모으는 것은 의미 론적입니다. (SQL 조인 작업 일 필요는 없음)
Sylhare

1

세 가지 데이터 프레임은

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

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

중첩 된 pd.merge를 사용하여 이러한 프레임을 병합합시다

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

여기에 병합 된 데이터 프레임이 있습니다.

행복한 분석 !!!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.