programing

팬더 병합 - 열 중복 방지 방법

javajsp 2023. 6. 8. 19:22

팬더 병합 - 열 중복 방지 방법

두 데이터 프레임을 병합하려고 합니다.각 데이터 프레임에는 두 개의 인덱스 수준(날짜, cusip)이 있습니다.예를 들어, 열에서 일부 열은 두 열(통화, 조정 날짜) 사이에 일치합니다.

이것들을 색인별로 병합하되 통화와 조정 날짜를 두 개 가져가지 않는 가장 좋은 방법은 무엇입니까?

각각의 데이터 프레임은 90개의 열로 구성되어 있어서, 저는 모든 것을 손으로 쓰는 것을 피하려고 노력하고 있습니다.

df:                 currency  adj_date   data_col1 ...
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45
...

df2:                currency  adj_date   data_col2 ...
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45
...

내가 할 경우:

dfNew = merge(df, df2, left_index=True, right_index=True, how='outer')

알겠습니다

dfNew:              currency_x  adj_date_x   data_col2 ... currency_y adj_date_y
date        cusip
2012-01-01  XSDP      USD      2012-01-03   0.45             USD         2012-01-03

감사합니다!

하나의 데이터 프레임에만 있는 열을 해결하고 이 열을 사용하여 병합에서 열의 하위 집합을 선택할 수 있습니다.

cols_to_use = df2.columns.difference(df.columns)

그런 다음 병합을 수행합니다(이것은 인덱스 개체이지만 유용합니다).tolist()방법)을 선택합니다.

dfNew = merge(df, df2[cols_to_use], left_index=True, right_index=True, how='outer')

이렇게 하면 병합 시 열이 충돌하지 않습니다.

나는 사용합니다.suffixes다음 옵션drop():

dfNew = df.merge(df2, left_index=True, right_index=True,
                 how='outer', suffixes=('', '_y'))

dfNew.drop(dfNew.filter(regex='_y$').columns, axis=1, inplace=True)

@ijoseph 감사합니다.

@rprog의 답변을 바탕으로, 음의 정규식을 사용하여 접미사와 필터 단계의 다양한 부분을 한 줄로 결합할 수 있습니다.

dfNew = df.merge(df2, left_index=True, right_index=True,
             how='outer', suffixes=('', '_DROP')).filter(regex='^(?!.*_DROP)')

또는 사용df.join:

dfNew = df.join(df2, lsuffix="DROP").filter(regex="^(?!.*DROP)")

여기서 정규식은 "DROP"로 끝나지 않는 모든 것을 유지하므로 열에 아직 나타나지 않는 접미사를 사용해야 합니다.

저는 Panda에 새로 가입했지만 _x 또는 _y가 있는 열 이름을 자동으로 피하고 중복 데이터를 제거하여 동일한 작업을 수행하고 싶었습니다.는 이 답변과 스택 오버플로의 이 답변을 사용하여 마침내 그것을 했습니다.

판매.csv

도시;주;주;주멘도시노;CA;1덴버;CO;4오스틴;TX;2

수익.csv

branch_id;city;city;state_id10; 오스틴; 100;TX20; 오스틴; 83;TX30; 오스틴; 4;TX47; 오스틴; 200;TX20;덴버;83;CO30;스프링필드;4;i

merge.py 수입 판다

def drop_y(df):
    # list comprehension of the cols that end with '_y'
    to_drop = [x for x in df if x.endswith('_y')]
    df.drop(to_drop, axis=1, inplace=True)


sales = pandas.read_csv('data/sales.csv', delimiter=';')
revenue = pandas.read_csv('data/revenue.csv', delimiter=';')

result = pandas.merge(sales, revenue,  how='inner', left_on=['state'], right_on=['state_id'], suffixes=('', '_y'))
drop_y(result)
result.to_csv('results/output.csv', index=True, index_label='id', sep=';')

병합 명령을 실행할 때 다음을 대체합니다._x빈 문자열로 끝나는 열을 제거할 수 있는 접미사_y

출력.csv

id;city;state;vmdk;vmdk_id;vmdk;state_id0;덴버;CO;4;20;83;CO1; 오스틴;TX;2;10;100;TX2; 오스틴;TX;2;20;83;TX3; 오스틴;TX;2;30;4;TX4; 오스틴;TX;2;47;200;TX

이것은 문제를 우회하는 것이지만, 기본적으로 추가 열을 다루는 함수를 작성했습니다.

def merge_fix_cols(df_company,df_product,uniqueID):
    
    df_merged = pd.merge(df_company,
                         df_product,
                         how='left',left_on=uniqueID,right_on=uniqueID)    
    for col in df_merged:
        if col.endswith('_x'):
            df_merged.rename(columns = lambda col:col.rstrip('_x'),inplace=True)
        elif col.endswith('_y'):
            to_drop = [col for col in df_merged if col.endswith('_y')]
            df_merged.drop(to_drop,axis=1,inplace=True)
        else:
            pass
    return df_merged

내 병합과 잘 맞는 것 같습니다!

중복 항목을 제거할 수 있습니다.y조인 후 사용하지 않을 열:

# Join df and df2
dfNew = merge(df, df2, left_index=True, right_index=True, how='inner')

출력:currency_x | adj_date_x | data_col1 | ... | currency_y | adj_date_y | data_col2

# Remove the y columns by selecting the columns you want to keep
dfNew = dfNew.loc[:, ("currency_x", "adj_date_x", "data_col1", "data_col2")]

출력:currency_x | adj_date_x | data_col1 | data_col2

먼저 df의 열을 부분 집합으로 설정할 수 없습니까?

[i for i in df.columns if i not in df2.columns]
dfNew = merge(df **[i for i in df.columns if i not in df2.columns]**, df2, left_index=True, right_index=True, how='outer')

사용하지 않을 열의 양이 유지할 열보다 작을 경우...다음과 같은 필터링을 사용할 수 있습니다.

df.loc[:, ~df.columns.isin(['currency', 'adj_date'])]

이렇게 하면 'currency' 및 'adj_date' 열을 제외한 데이터 프레임의 모든 열이 필터링되므로 병합을 다음과 같이 작성해야 합니다.

    dfNew = merge(df, 
                  df2.loc[:, ~df.columns.isin(['currency', 'adj_date'])], 
                  left_index=True,
                  right_index=True,
                  how='outer')

"~"는 "아니오"를 의미합니다.

키에 중복 열을 포함하여 병합하여 결과에 단일 복사본만 표시할 수 있습니다.

# Generate some dummy data.
shared = pd.DataFrame({'key': range(5), 'name': list('abcde')})
a = shared.copy()
a['value_a'] = np.random.normal(0, 1, 5)
b = shared.copy()
b['value_b'] = np.random.normal(0, 1, 5)

# Standard merge.
merged = pd.merge(a, b, on='key')
print(merged.columns)  # Index(['key', 'name_x', 'value_a', 'name_y', 'value_b'], dtype='object')

# Merge with both keys.
merged = pd.merge(a, b, on=['key', 'name'])
print(merged.columns)  # Index(['key', 'name', 'value_a', 'value_b'], dtype='object')

이 방법을 사용하면 두 데이터 프레임에 모두 나타나는 열의 값이 일관되게 유지됩니다(예: 두 열의 통화가 동일해야 함).됩니다(만약 "" "" "" "" "" "" "" ""일 경우").how = 'inner' 합니다.how = 'outer').

임의의 열에 병합하는 경우 올바른 키를 유지하지 않으려면 다음과 같이 하십시오.

mrg = pd.merge(a, b, how="left", left_on="A_KEY", right_on="B_KEY")
mrg.drop(columns=b.columns.difference(cols_to_use))

인덱스가 동일한 경우(참인 경우 큼!) 다음 작업을 수행할 수 있습니다.

df = df1.copy()
df[df2.columns] = df2

은 이와유한과 merge

pd.merge(df1, df2, index_left=True, index_right=True)

중복된 열이 없는 경우

언급URL : https://stackoverflow.com/questions/19125091/pandas-merge-how-to-avoid-duplicating-columns