Estou tentando uma fusão entre dois quadros de dados. Cada quadro de dados tem dois níveis de índice (data, cúspide). Nas colunas, algumas colunas correspondem entre os dois (moeda, data de ajuste), por exemplo.
Qual é a melhor maneira de mesclar estes por índice, mas não levar duas cópias da moeda e data de ajuste.
Cada quadro de dados tem 90 colunas, então estou tentando evitar escrever tudo à mão.
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
...
Se eu fizer:
dfNew = merge(df, df2, left_index=True, right_index=True, how='outer')
eu recebo
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
Obrigado! ...
Eu uso a
suffixes
opção em.merge()
:dfNew = df.merge(df2, left_index=True, right_index=True, how='outer', suffixes=('', '_y')) dfNew.drop(dfNew.filter(regex='_y$').columns.tolist(),axis=1, inplace=True)
Obrigado @ijoseph
fonte
filter
ing (que é bastante simples, mas ainda assim demorado para pesquisar / sujeito a erros de lembrar). iedfNew.drop(list(dfNew.filter(regex='_y$')), axis=1, inplace=True)
Com base na resposta de @rprog, você pode combinar as várias partes do sufixo e etapa do filtro em uma linha usando um regex negativo:
dfNew = df.merge(df2, left_index=True, right_index=True, how='outer', suffixes=('', '_DROP')).filter(regex='^(?!.*_DROP)')
Ou usando
df.join
:dfNew = df.join(df2, lsuffix="DROP").filter(regex="^(?!.*DROP)")
A regex aqui está mantendo tudo que não termine com a palavra "DROP", então certifique-se de usar um sufixo que já não apareça entre as colunas.
fonte
Eu sou novo no Pandas, mas queria conseguir a mesma coisa, evitando automaticamente nomes de coluna com _x ou _y e removendo dados duplicados. Eu finalmente o fez usando essa resposta e este um dos Stackoverflow
sales.csv
receita.csv
merge.py import pandas
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=';')
Ao executar o comando de mesclagem, substituo o
_x
sufixo por uma string vazia e posso remover as colunas que terminam com_y
output.csv
fonte
Isso é um pouco para contornar o problema, mas escrevi uma função que basicamente lida com as colunas extras:
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
Parece funcionar bem com minhas mesclagens!
fonte
você não pode apenas definir subconjuntos das colunas em qualquer um dos df primeiro?
[i para i em df.columns se eu não estiver em df2.columns]
dfNew = merge (df [i for i in df.columns se i não estiver em df2.columns] , df2, left_index = True, right_index = True, how = 'outer')
fonte