열에서 여러 데이터 프레임을 결합하는 팬더 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의 python
3.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')
예 : 명령 )
The join
operation is by default performed on index. In your case, you just have to specify that the Name
column corresponds to your index. Below is an example
A tutorial may be useful.
# 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')
Here is a method to merge a dictionary of data frames while keeping the column names in sync with the dictionary. Also it fills in missing values if needed:
This is the function to merge a dict of data frames
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)
OK, lets generates data and test this:
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)
There is another solution from the pandas documentation (that I don't see here),
using the .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
The ignore_index=True
is used to ignore the index of the appended dataframe, replacing it with the next index available in the source one.
If there are different column names, Nan
will be introduced.
Simple Solution:
If the column names are similar:
df1.merge(df2,on='col_name').merge(df3,on='col_name')
If the column names are different:
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'})
참고URL : https://stackoverflow.com/questions/23668427/pandas-three-way-joining-multiple-dataframes-on-columns
'development' 카테고리의 다른 글
AsyncTask에 전달되는 인수 (0) | 2020.06.08 |
---|---|
모든 사용자 테이블을 삭제하는 방법? (0) | 2020.06.08 |
AngularJS의 범위에서 항목을 제거하는 방법은 무엇입니까? (0) | 2020.06.08 |
PHP 부분 문자열 추출. (0) | 2020.06.08 |
조건문을 단축하는 방법 (0) | 2020.06.08 |