加入并分组 2 个数据框
join and groupby 2 dataframes
我有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)
我 'believe' 这个公式有效,但我说 'I believe' 因为我在技术上还没有看到结果 df 因为 df_ServicesA 是一个很长的迭代列表和数量df_ServicesB 上的客户端也很长,使得迭代过程呈指数增长,以至于 lambda 函数已经 运行 几次,但要么没有错误地失败,要么在一夜之间超时,我得到了当我到我的电脑上查看结果时断开连接。目前它已经 运行ning 了 4 个小时,但我仍然没有得到结果 df dataset/frame。
也许有更 pythonic 的方法来做到这一点?或者也许是一种提高效率的方法,这样它就不会花很长时间?
提前致谢
给你:
我用 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
您可以对您的第一个数据框进行分组并计算组数:
# 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
我有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'
的新 dfdf = 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)
我 'believe' 这个公式有效,但我说 'I believe' 因为我在技术上还没有看到结果 df 因为 df_ServicesA 是一个很长的迭代列表和数量df_ServicesB 上的客户端也很长,使得迭代过程呈指数增长,以至于 lambda 函数已经 运行 几次,但要么没有错误地失败,要么在一夜之间超时,我得到了当我到我的电脑上查看结果时断开连接。目前它已经 运行ning 了 4 个小时,但我仍然没有得到结果 df dataset/frame。
也许有更 pythonic 的方法来做到这一点?或者也许是一种提高效率的方法,这样它就不会花很长时间?
提前致谢
给你: 我用 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
您可以对您的第一个数据框进行分组并计算组数:
# 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