如何使用Python按集合列合并?
我有两个堆栈溢出问题列表,A组和B组。它们都有两列,Id和Tag。e、 g:如何使用Python按集合列合并?,python,pandas,dataframe,merge,set,Python,Pandas,Dataframe,Merge,Set,我有两个堆栈溢出问题列表,A组和B组。它们都有两列,Id和Tag。e、 g: |Id |Tag | -------- | -------------------------------------------- |2 |c#,winforms,type-conversion,decimal,opacity 对于A组中的每个问题,我需要在B组中找到所有匹配的问题,这些问题至少有一个重叠的标签——A组中的问题,与标签的位置无关。例如,这些问题都应该是匹配的问题: |I
|Id |Tag
| -------- | --------------------------------------------
|2 |c#,winforms,type-conversion,decimal,opacity
对于A组中的每个问题,我需要在B组中找到所有匹配的问题,这些问题至少有一个重叠的标签——A组中的问题,与标签的位置无关。例如,这些问题都应该是匹配的问题:
|Id |Tag
|----------|---------------------------
|3 |c#
|4 |winforms,type-conversion
|5 |winforms,c#
我的第一个想法是将变量标记转换成一个set变量,并使用Pandas合并,因为set忽略位置。然而,Pandas似乎不允许set变量作为关键变量。所以我现在使用for循环来搜索B组,但是速度非常慢,因为我在B组有1300万次观察
我的问题是:
1.Python中是否有其他方法可以通过一列集合进行合并,并可以判断重叠标记的数量?
2.如何提高for循环搜索的效率?这可以通过使用
df.join
和df.groupby
实现
这是我正在使用的设置:
df1 = pd.DataFrame({ 'Id' : [2], 'Tag' : [['c#', 'winforms', 'type-conversion', 'decimal', 'opacity']]})
Id Tag
0 2 [c#, winforms, type-conversion, decimal, opacity]
df2 = pd.DataFrame({ 'Id' : [3, 4, 5], 'Tag' : [['c#'], ['winforms', 'type-conversion'], ['winforms', 'c#']]})
Id Tag
0 3 [c#]
1 4 [winforms, type-conversion]
2 5 [winforms, c#]
让我们将两个数据帧中的右列展平。帮助:
类似地,df2也是扁平的
现在是魔术。我们将在Tag
列上执行join
,然后在joinedID
s上执行groupby
,以查找重叠标记的计数
In [2337]: df1.merge(df2, on='Tag').groupby(['Id_x', 'Id_y']).count().reset_index()
Out[2337]:
Id_x Id_y Tag
0 2 3 1
1 2 4 2
2 2 5 2
输出显示每对标记以及重叠标记的数量。无重叠的对由groupby
过滤掉
df.count
对重叠的标记进行计数,df.reset_index
只是美化输出,因为groupby
将分组列指定为索引,所以我们将其重置
要查看匹配的标记,您将稍微修改上面的内容:
In [2359]: df1.merge(df2, on='Tag').groupby(['Id_x', 'Id_y'])['Tag'].apply(list).reset_index()
Out[2359]:
Id_x Id_y Tag
0 2 3 [c#]
1 2 4 [winforms, type-conversion]
2 2 5 [c#, winforms]
要过滤出1-重叠,请链adf.query
调用第一个表达式:
In [2367]: df1.merge(df2, on='Tag').groupby(['Id_x', 'Id_y']).count().reset_index().query('Tag > 1')
Out[2367]:
Id_x Id_y Tag
1 2 4 2
2 2 5 2
- 第1步列出所有标签
- 步骤2:创建每个标签的二进制表示,即使用位1或0表示是否有标签
- 步骤3:要查找共享同一标记的任何ID,可以调用一个简单的apply函数来解码二进制表示
(本打算留下评论,但声誉不够……唉)你是如何得到1300万个堆栈溢出问题的?API永远不会让你这么快完成。我是从Stack Exchange data dumps@COLDSPEEDOkay下载的。下一个问题。标签是由逗号分隔的标签组成的字符串类型还是标签列表?标签是由括号分隔的标签组成的字符串。但我可以使用正则表达式将其转换为标记列表。我现在正在读你的答案,看起来很有希望。非常感谢你!至少有一万个标签。如果我使用二进制表示,我将有数千列来表示问题的标记。如果超过一万个标签,我认为你不应该使用我上面提出的方法。我认为Coldspeed使用的方法会更好。有没有办法也显示重叠的标签?@Coldspeed抱歉,我以前忘了提到。我可以在连接时限制重叠标记的数量吗?因为有太多带有一个或两个重叠标记的问题,这会使输出表太长。所以我想把问题限制在只有3个或更多重叠标签的问题上。谢谢@小萌用
.query
,我在我的帖子中编辑。从现在开始,请不要在评论中重复要求和细节。它妨碍了未来读者的可读性。请一次查询一个问题。如果这解决了您的问题,请将其标记为已接受并提出新问题。我将不再回答注释中的任何问题。@COLDSPEED我在展平df2时遇到问题,它给出错误“根据规则“安全”将数组数据从dtype('float64')转换为dtype('int64')”。在从csv文件导入df2时,我已尝试使用dtype=int64。但我还是犯了同样的错误。但是,使用函数展平df1没有问题。df1和df2之间的唯一区别是df2比df1有更多的观测值。而df2.Id列的int可能更长。@Xiaomeng肯定会问一个新问题。我想我不知道如何解决内存错误!
In [2367]: df1.merge(df2, on='Tag').groupby(['Id_x', 'Id_y']).count().reset_index().query('Tag > 1')
Out[2367]:
Id_x Id_y Tag
1 2 4 2
2 2 5 2