join和groupby 2个数据帧



我有两个数据帧

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上迭代,它非常慢。这应该是你最后的资源。几乎总有更好的办法。在本例中,您想要查看groupbymerge。你应该阅读这些指南

  1. https://pandas.pydata.org/docs/user_guide/groupby.html
  2. 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

最新更新