首页 > 解决方案 > 在 Python 中比较 2 个 DataFrame 时出现问题,应排除所有重复项,但工作不正常

问题描述

我正在开发连接 Google Analytics 到 SQL Server 数据库的连接器,但存在重复值问题。

首先,该脚本使用 GA Accounts 配置解析嵌套 dict,然后将其转换为 pandas df 并将所有响应存储在一个列表中,然后获取包含所有 GA 数据的当前 SQL 表并循环比较新值(来自 GA API)并生成当前值(在 sql 表中)。

但由于某种原因,在比较这 2 个 dfs 时,所有重复项都被保留了。

如果有人可以提供帮助,我会非常高兴。

用于发出 GA API 请求的带有配置的嵌套字典


data_test = {
    
    'view_id_111' : {'view_id': '111', 
                           'start_date': '2019-08-01', 
                           'end_date': '2019-09-01',
                           'metrics': [{'expression': 'ga:sessions'}, {'expression':'ga:users'}],
                           'dimensions': [{'name': 'ga:country'}, {'name': 'ga:userType'}, {'name': 'ga:date'}]},
    
     'view_id_222' : {'view_id': '222', 
                           'start_date': '2019-08-01', 
                           'end_date': '2019-09-01',
                           'metrics': [{'expression': 'ga:sessions'}, {'expression':'ga:users'}],
                           'dimensions': [{'name': 'ga:country'}, {'name': 'ga:date'}]},
    
    'view_id_333' : {'view_id': '333', 
                           'start_date': '2019-01-01', 
                           'end_date': '2019-05-01',
                           'metrics': [{'expression': 'ga:sessions'}, {'expression':'ga:users'}],
                           'dimensions': [{'name': 'ga:country'}, {'name': 'ga:date'}]} 
}

  1. 向 Google API 发送请求,将其转换为 df 并将值存储在列表中
responses = []

for k, v in data_test.items():
    
    sample_request = {
        'viewId': v['view_id'],
        'dateRanges': {
            'startDate': v['start_date'],
            'endDate': v['end_date']
        },
        'metrics': v['metrics'],
        'dimensions': v['dimensions']
    }
    
    response = analytics.reports().batchGet(
        body={
            'reportRequests': sample_request
        }).execute()
    
    n_response=print_response_new_test(response)
    responses.append(n_response)
  1. 使用 GA 数据获取当前 SQL 表
def get_current_sql_gadata_table():
    global sql_table_current_gadata
    sql_table_current_gadata = pd.read_sql('SELECT * FROM Table', con=conn)
    sql_table_current_gadata['date'] = pd.to_datetime(sql_table_current_gadata['date'])
    return sql_table_current_gadata
  1. 最后比较2个DF,如果有差异,更新SQL表

def compare_df_gadata():
    
    for report in responses:
        response=pd.DataFrame.equals(sql_table_current_gadata, report)
        if response==False:
            compared_dfs = pd.concat([sql_table_current_gadata, report], sort=False)
            compared_dfs.drop_duplicates(keep=False, inplace=True)
    
            #sql params in sqlalchemy
            params = urllib.parse.quote_plus(#params)
            engine = create_engine('mssql+pyodbc:///?odbc_connect={}'.format(params))

            #insert new values to the sql table
            compared_dfs.to_sql('Table', con=engine, if_exists='append', index=False)
          

我也尝试过合并 2 个表,但结果是一样的。也许签入MS Studio更合理?

也不能正常工作

df_outer = pd.merge(sql_table_current_gadata, report, on=None, how='left', sort=True)

更新

我又用 concat 函数检查了一次,看起来问题出在“索引”中。

原来的 240 行(960 行已经有重复,所以只需清理 SQL 表并再次运行脚本)。

我有 3 个 GA 帐户,当前 SQL 表由这些帐户组成:72 行 + 13 行 + 154 行 + 标题 = 240 行。

再次运行脚本时,与 pd.concat 进行比较并将结果存储在数据帧 (compared_dfs) 中(不将其发送到数据库),它包含从最后一次请求到 GA API 的 154 行。

我试图在这里重置:

if response==False:
            compared_dfs = pd.concat([sql_table_current_gadata, report], sort=False)
            compared_dfs.drop_duplicates(keep=False, inplace=True)
            compared_dfs.reset_index(inplace=True)

但结果,它被添加为 compare_dfs 中的附加列

结果DF

它显示了 2 个索引列,一个来自 SQL 表,另一个来自 pandas

标签: pythonsqlpandasduplicatesgoogle-analytics-api

解决方案


你的问题很详细,但很清楚。我首先会问您是否确定您的索引,您可以尝试合并特定列以查看这是否解决了问题?我首先关注熊猫部分,因为这似乎是您问题的重点。

import pandas as pd
import numpy as np

merge = True
concat = False

anp = np.ones((2, 5))
anp[1, 1] = 3
anp[1, 4] = 3
bnp = np.ones((1, 5))
bnp[0, 1] = 4  # use 4 to make it different, also works with nan
bnp[0, 4] = 4  # use 4 to make it different, also works with nan
a = pd.DataFrame(anp)
b = pd.DataFrame(bnp)
if merge:
    a.rename(columns=dict(zip(range(5), ['a', 'b', 'c', 'd', 'e'])), inplace=True)
    b.rename(columns=dict(zip(range(5), ['a', 'b', 'c', 'd', 'e'])), inplace=True)
    # choose suitable and meaningful column(s) for your merge (do you have any id column etc.?)
    a = pd.merge(a, b, how='outer', copy=False, on=['a', 'c', 'd', 'e'])
    # che
    print(a)

if concat:
    # can use ignore_index or pass keys to maintain distiction
    c = pd.concat((a, b), axis=0, join='outer', keys=['a', 'b'])
    print(c)
    c.drop_duplicates(inplace=True)
    print(c)


推荐阅读