pandas 字符串列的交集/子集
Intersection / subset of pandas string columns
我有一个 pandas 数据框,其付款结构如下:
>> print(df)
id time amount seller buyer
-------------------------------------------------
1 07:01 16.00 Jack Rose
2 07:03 14.00 Alice Bob
3 07:05 95.00 Jim Larry
... ... ... ... ...
9999 18:16 81.00 Rose Alice
如何从中找到 "closed-members" 支付网络?
例如,如果我想找到只包含{Rose、Alice、Jim}彼此之间严格付款的数据子集,则以下可能有效:
members = ['Rose', 'Alice', 'Jim']
df_subset = df[df.seller.isin(members) & df.buyer.isin(members)]
但是如何检索最大的此类网络?即不仅针对 3 个人,而且针对数据框中的最大可能人数?
我已经尝试过以下变体:
df_subset = df[df.seller.isin(df.buyer.unique())]
df_subset = df_subset[df_subset.buyer.isin(df_subset.seller.unique())]
然而,这并不成功,因为之后 df_subset.seller.unique()
和 df_subset.buyer.unique()
不一样。
如有任何帮助,我们将不胜感激。
相信最后df_subset.seller.unique()
和df_subset.buyer.unique()
应该是一样的
这就是你要找的最大人数
a = df[df.seller].drop_duplicates()
b = df[df.buyer].drop_duplicates()
result = pd.concat([a,b])
IIUC,下面应该做你想做的:
common_users = set(df["buyer"]).intersection(df["seller"])
df_subset = df[df["buyer"].isin(common_users) & df["seller"].isin(common_users)]
以下解决方案似乎有效。我将提供一个沙盒解决方案,因为它可能对其他人有用。
首先,让我们定义一个与问题中类似的 pandas 数据框:
# generates strings to be used as names, e.g.: 'hlddldxhys'
def randomString(stringLength=10):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
# let's generate a set of 600 names
participants = [];
for k in range(600):
participants.append(randomString())
# from the generated set, draw 1000 sellers and buyers
seller = np.random.choice(participants, 1000)
buyer = np.random.choice(participants, 1000)
# construct pandas data frame
df = pd.DataFrame([seller, buyer]).T
df.columns = ['seller', 'buyer']
查看结果数据框 print(df)
:
seller buyer
----------------------------
0 bpzroghaxp evvhhlbiys
1 qsopxbirgn lwwljadfwg
2 cnllyrzjiz opbvoodpgw
3 hkzafylzst slfqtwdeak
... ... ...
999 natqsscnlk ftvjvgtala
虽然有些人暗示了一个解决方案(来自 PMende、Tal Avissar 和我自己的回复),但它似乎确实有效 - 但只是迭代,其中每次迭代df = df[df.seller.isin(df.buyer.unique()) & df.buyer.isin(df.seller.unique())]
df.seller.unique()
和 df.buyer.unique()
的集合变得更加相似。重复此操作直到它们相同(请参阅最后一个 if-statement,然后是 break
):
while(True):
df = df[df.seller.isin(df.buyer.unique()) & df.buyer.isin(df.seller.unique())]
if len(df.seller.unique()) == len(df.buyer.unique()):
if (np.sort(df.seller.unique()) == np.sort(df.buyer.unique())).all() == True:
break
最终检查确认,df.seller.unique()
和 df.buyer.unique()
的长度相同,组成也相同:
>> len(df.seller.unique()), len(df.buyer.unique())
(281, 281)
>> (np.sort(df.seller.unique()) == np.sort(df.buyer.unique())).all()
True
下图显示了 df.seller.unique()
和 df.buyer.unique()
的集合如何随着循环的每次迭代变得彼此相似:
See also charts: visualisation of solution
我有一个 pandas 数据框,其付款结构如下:
>> print(df)
id time amount seller buyer
-------------------------------------------------
1 07:01 16.00 Jack Rose
2 07:03 14.00 Alice Bob
3 07:05 95.00 Jim Larry
... ... ... ... ...
9999 18:16 81.00 Rose Alice
如何从中找到 "closed-members" 支付网络?
例如,如果我想找到只包含{Rose、Alice、Jim}彼此之间严格付款的数据子集,则以下可能有效:
members = ['Rose', 'Alice', 'Jim']
df_subset = df[df.seller.isin(members) & df.buyer.isin(members)]
但是如何检索最大的此类网络?即不仅针对 3 个人,而且针对数据框中的最大可能人数?
我已经尝试过以下变体:
df_subset = df[df.seller.isin(df.buyer.unique())]
df_subset = df_subset[df_subset.buyer.isin(df_subset.seller.unique())]
然而,这并不成功,因为之后 df_subset.seller.unique()
和 df_subset.buyer.unique()
不一样。
如有任何帮助,我们将不胜感激。
相信最后df_subset.seller.unique()
和df_subset.buyer.unique()
应该是一样的
这就是你要找的最大人数
a = df[df.seller].drop_duplicates()
b = df[df.buyer].drop_duplicates()
result = pd.concat([a,b])
IIUC,下面应该做你想做的:
common_users = set(df["buyer"]).intersection(df["seller"])
df_subset = df[df["buyer"].isin(common_users) & df["seller"].isin(common_users)]
以下解决方案似乎有效。我将提供一个沙盒解决方案,因为它可能对其他人有用。
首先,让我们定义一个与问题中类似的 pandas 数据框:
# generates strings to be used as names, e.g.: 'hlddldxhys'
def randomString(stringLength=10):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
# let's generate a set of 600 names
participants = [];
for k in range(600):
participants.append(randomString())
# from the generated set, draw 1000 sellers and buyers
seller = np.random.choice(participants, 1000)
buyer = np.random.choice(participants, 1000)
# construct pandas data frame
df = pd.DataFrame([seller, buyer]).T
df.columns = ['seller', 'buyer']
查看结果数据框 print(df)
:
seller buyer
----------------------------
0 bpzroghaxp evvhhlbiys
1 qsopxbirgn lwwljadfwg
2 cnllyrzjiz opbvoodpgw
3 hkzafylzst slfqtwdeak
... ... ...
999 natqsscnlk ftvjvgtala
虽然有些人暗示了一个解决方案(来自 PMende、Tal Avissar 和我自己的回复),但它似乎确实有效 - 但只是迭代,其中每次迭代df = df[df.seller.isin(df.buyer.unique()) & df.buyer.isin(df.seller.unique())]
df.seller.unique()
和 df.buyer.unique()
的集合变得更加相似。重复此操作直到它们相同(请参阅最后一个 if-statement,然后是 break
):
while(True):
df = df[df.seller.isin(df.buyer.unique()) & df.buyer.isin(df.seller.unique())]
if len(df.seller.unique()) == len(df.buyer.unique()):
if (np.sort(df.seller.unique()) == np.sort(df.buyer.unique())).all() == True:
break
最终检查确认,df.seller.unique()
和 df.buyer.unique()
的长度相同,组成也相同:
>> len(df.seller.unique()), len(df.buyer.unique())
(281, 281)
>> (np.sort(df.seller.unique()) == np.sort(df.buyer.unique())).all()
True
下图显示了 df.seller.unique()
和 df.buyer.unique()
的集合如何随着循环的每次迭代变得彼此相似:
See also charts: visualisation of solution