我来自Excel背景,但我喜欢大熊猫,它确实让我更有效率。不幸的是,我可能从Excel中带来了一些不良习惯。我有三个大文件(每个文件在200万到1300万行之间),其中包含可以绑定在一起的交互数据,遗憾的是,没有连接文件的唯一键。我将3个字段连接到所有三个文件的一个新列中。
我合并在一起的每个文件上存在三个列(其他字段就像是在一个文件上进行交互的原因,另一个文件上的分数,以及我想要关联的第三个文件上的其他一些数据一起回到某个agentID):
Date | CustomerID | AgentID
我在每个文件上编辑我的日期格式:
df[Date] = pd.to_datetime(df['Date'], coerce = True)
df[Date] = df[Date].apply(lambda x:x.date().strftime('%Y-%m-%d'))
然后我创建了一个独特的列(好吧,因为我可以得到它唯一...有时同一个客户在同一天与同一个代理进行交互,但这应该是非常罕见的):
df[Unique] = df[Date].astype(str) + df[CustomerID].astype(str) + df[AgentID].astype(str)
我为df2执行相同的步骤,然后:
combined = pd.merge(df, df2, how = 'left', on = 'Unique')
我通常将它发送到新的csv以防万一崩溃,gzip,然后再次读取它并再次使用第三个文件执行相同的过程。
final = pd.merge(combined, df2, how = 'left', on = 'Unique')
如您所见,这需要时间。我必须格式化每个日期,然后将它们转换为文本,创建一个添加到文件大小的对象列,并(由于原始数据问题本身)删除重复项,所以我不会意外地膨胀数字。我有更高效的工作流程吗?
答案 0 :(得分:3)
而不是使用on = 'Unique'
:
combined = pd.merge(df, df2, how = 'left', on = 'Unique')
您可以将列表列表传递给on
关键字参数:
combined = pd.merge(df, df2, how='left', on=['Date', 'CustomerID', 'AgentID'])
Pandas将根据'Date', 'CustomerID', 'AgentID'
列的三元组值正确合并行。这比建立Unique列更安全(见下文)并且更容易。
例如,
import pandas as pd
import numpy as np
np.random.seed(2015)
df = pd.DataFrame({'Date': pd.to_datetime(['2000-1-1','2000-1-1','2000-1-2']),
'CustomerID':[1,1,2],
'AgentID':[10,10,11]})
df2 = df.copy()
df3 = df.copy()
L = len(df)
df['ABC'] = np.random.choice(list('ABC'), L)
df2['DEF'] = np.random.choice(list('DEF'), L)
df3['GHI'] = np.random.choice(list('GHI'), L)
df2 = df2.iloc[[0,2]]
combined = df
for x in [df2, df3]:
combined = pd.merge(combined, x, how='left', on=['Date','CustomerID', 'AgentID'])
产量
In [200]: combined
Out[200]:
AgentID CustomerID Date ABC DEF GHI
0 10 1 2000-1-1 C F H
1 10 1 2000-1-1 C F G
2 10 1 2000-1-1 A F H
3 10 1 2000-1-1 A F G
4 11 2 2000-1-2 A F I
警告:
将CustomerID添加到AgentID以创建唯一ID可能会有问题 - 特别是如果两者都没有固定宽度的格式。
例如,如果CustomerID = '12'
和AgentID = '34'
那么(忽略导致没有问题的日期,因为它确实有固定宽度)Unique
'1234'
。但是如果CustomerID = '1'
和AgentID = '234'
那么Unique
会
再次等于'1234'
。因此Unique
ID可能完全不同
客户/代理商对。
PS。将日期字符串解析为类似日期的对象
是个好主意df['Date'] = pd.to_datetime(df['Date'], coerce=True)
请注意,如果您使用
combined = pd.merge(combined, x, how='left', on=['Date','CustomerID', 'AgentID'])
没有必要将任何列转换回字符串。