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

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

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

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



답변

가정 수입 :

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


답변

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')


답변

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


답변

데이터 프레임 목록에 대해 다음과 같이 수행 할 수도 있습니다 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')


답변

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']
)


답변

조인 작업 을 수행하기 위해 다중 인덱스가 필요하지 않습니다 . 조인 작업을 수행 할 인덱스 열을 올바르게 설정하면됩니다 ( 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')


답변

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

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

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)