我有两个数据帧
df:ServicesA df:ServicesB
index clientID ServiceID_A | index ClientID ServiceID_B
0 A 1 | 0 A 4
1 B 2 | 1 B 5
2 C 3 | 2 D 6
2 B 4 |
我想获得一个新的df,显示df:ServicesB上的客户端以及这些客户端拥有多少个servicesA。就像这样
index ClientID With ServiceID_B count(ServiceID_A)
0 A 1
1 B 2
2 D 0
我试过了:
我从df:ServicesB中获得了客户端ID的唯一列表,并创建了一个名为'df'的新df
df = pd.DataFrame(df_ServicesB['Client ID', ].unique(),columns=['Client ID'])
然后我使用这个lambda函数它将从df中获取每个客户端id并遍历df:ServicesA计算那些具有客户端id的行(相当于计算该数据帧
上的serviceidA)def getTotaldfServicesA(clientid):
total_services = 0
for index, row in df_ServicesA.iterrows():
if row['ClientID'] == clientid:
total_services += 1
return total_services
df['Total_servicesA'] = df.apply(lambda row: getTotaldfServicesA(row['ClientID']),axis=1)
我"相信"公式的工作但我说'我相信'因为我在技术上还没有看到结果df df_ServicesA是一个很长的列表遍历和客户的数量df_ServicesB长也使得迭代过程指数,lambda函数运行几次但是失败了,没有错误或超时一夜之间,我已经断开连接的时候我去我的电脑看到结果。目前它已经运行了4个小时,我仍然没有得到结果df dataset/frame。
也许有一种更python的方法来做到这一点?或者是一种更有效的方法,这样就不会花太长时间了?
提前谢谢你
可以对第一个数据帧进行分组并计数:
# Assuming that df:ServicesA is df_a
grouped = df_a.groupby("clientID").count()
>>> grouped
ServiceID_A
clientID
A 1
B 2
C 1
之后,您可以使用merge
函数左外连接组上的第二个数据帧:
# Assuming that df:ServicesB is df_b
joined = df_b[["ClientID"]].merge(grouped, left_on="ClientID",
right_on="clientID", how="left").fillna(0)
>>> joined
clientID ServiceID_A
0 A 1.0
1 B 2.0
2 D 0.0
给你:我用csv文件测试了你的日期框架,它的工作:
sA = pd.read_csv("ServicesA.csv")
sB = pd.read_csv("ServicesB.csv")
count_dict = sA.groupby(['ClientID']).size().to_dict()
count_dict.setdefault('D',0)
sB['count(ServiceID_A)'] = sB.ClientID.replace(count_dict)
让我知道这是不工作
您应该始终避免在DataFrame/Series上迭代,它非常慢。这应该是你最后的资源。几乎总有更好的办法。在本例中,您想要查看groupby
和merge
。你应该阅读这些指南
- https://pandas.pydata.org/docs/user_guide/groupby.html
- https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html
这将比使用iterrows
>>> res = (
df_ServicesB.merge(df_ServicesA, how='left', on='ClientID')
.groupby('ClientID', as_index=False)
[['ServiceID_A']].count()
)
>>> res.columns = ["ClientID With ServiceID_B", "count(ServiceID_A)"]
>>> res
ClientID With ServiceID_B count(ServiceID_A)
0 A 1
1 B 2
2 D 0