python - 在 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'}]}
}
- 向 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)
- 使用 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
- 最后比较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 中的附加列
它显示了 2 个索引列,一个来自 SQL 表,另一个来自 pandas
解决方案
你的问题很详细,但很清楚。我首先会问您是否确定您的索引,您可以尝试合并特定列以查看这是否解决了问题?我首先关注熊猫部分,因为这似乎是您问题的重点。
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)
推荐阅读
- c# - Razor Pages @functions 块与代码块
- sql - SQLite - 迄今为止的时间戳
- oauth-2.0 - 如何获取令牌并同时隐藏 google drive 的 api 凭据?
- javascript - React-Router 不会渲染组件
- neo4j - 如何使用 Cypher 从 Neo4j 中的时间序列表构建折线图?
- android - 使用数据绑定后查看边距不起作用
- r - 在R中的data.frame的行上使用apply函数
- android - Osmdroid - 更改方向箭头的默认(白色)颜色(或如何自定义图标)
- laravel - 是否有任何指南来配置 Vuetify/Webpack 以使用 vuetify 加载程序?
- android - 导航组件:显示带圆角的对话框