z = list(zip(names, map(set, atts.str.split(';').tolist())))
dict_ = dict()
for i in range(len(z)):
for j in range(i+1, len(z)):
inter = (z[i][1].intersection(z[j][1]))
if inter:
dict_[(z[i][0], z[j][0])] = len(z[i][1].intersection(z[j][1]))
pd.DataFrame(dict_, index=['NumberAttributesShared']).T.reset_index()
假设没有重复的id,简单的解决方案如下
当然,在纯python中,不利用任何库作为
^{pr2}$itertools
。你明白了,可以试着做些改进因为我们使用的是
str
和set
的循环和集合,所以您可能不想为此使用pandas
。在纯python中工作,最后在pd.DataFrame
中输入输出从生成一个附加列开始,它是
AttributeList
的副本, 但是作为一个属性列表(而不是字符串或int):然后,要加快单个元素的读取,请将
^{pr2}$Name
复制到索引:然后可以计算每个2元素的公共属性的数量 名称组合:
最后,您可以生成结果:
^{4}$当然,您应该从
import itertools
开始。在编辑
您的示例数据只包含以“;”分隔的字符串。 现在,正如您所指出的,属性列表可以包含一个单个数字, 我意识到单个字段的类型可以是
string
或int
。在要正确读取这两种情况下的属性,请在
df['AttrList'] = ...
说明将右侧改为:(添加了
.astype(str)
以转换为正确的类型,我更改了这个细节 同上)。在如何解决性能问题
提示(但不是完整的解决方案)如何加快计算速度。在
生成辅助表:
只包含具有单个属性的行。在
我的示例数据包含具有单个属性的四行:
所以在我的例子中,
dfSgl
包含:然后执行:
在这种情况下:
这意味着}都有一个公共属性(4)。在
G
和{这可能不是这些物体的最终结果, 因为它们的(单个)属性可以出现在其他 具有多个属性的对象。在
然后你要把上面的“单子”和其他对象进行比较 对于多个属性,可以添加一些常用属性 对他们负责。在
剩下的部分是只比较具有多个属性的对象, 正如我在开头解释的那样,加入结果。所以至少 问题的规模会更小。在
编辑日期:2019年2月9日
我的第一个解决方案完全基于熊猫,但结果证明它是有效的 相对缓慢。在
所以我想出了另一个更快的解决方案,基于纽比和熊猫。在
其理念是:
将名称列设置为df的索引:
将Attr列添加到df,其中包含一个数字列表(属性):
它将需要计算每个对象的属性向量。在
我们需要一个辅助功能:
生成一个属性向量,其位置对应于 属性(数字)来自lst。第二个参数(len)指定 此向量的长度-最大属性+1(不使用元素0)。在
注意dtype='B'(无符号字节),基于假设 属性数小于256。相比之下,它降低了内存需求 默认值(在本例中)int类型。在
计算解的函数为:
第一部分是计算二维数组。每行代表数据 对于特定用户-一个由0和1组成的序列编码的属性列表。在
然后计数数组计算如下:
此解决方案的强大功能源于:
最后一步是计算(并返回)实际结果(DataFrame)。 值得注意的是:
所以唯一剩下的就是打电话:
我比较了执行时间和我的初始解决方案(使用%timeit), 在500个对象的样本数据中,从50个列表中最多有5个属性, 结果发现,这个解决方案速度快了10倍。在
最初我建议对 一个单独的属性,然后每个单独的属性都有多个属性,最后 每个对象都有多个属性(functionfun2not 包括在这里)。 但事实证明,这种解决方案的工作时间是前者的2.5倍 所以我撤销了这个命题。在
如果要将此结果与执行的计算结果进行比较 对于另一种方法,请使用以下“排序函数”:
它将Name1与Name2交换,并对行进行排序 NumberAttributesShared(降序),然后在两个名称上。 最后一步是重置索引。在
因此,您应该(针对每个结果)致电:
从各种方法得到的有序结果(或result和 或其他结果),您可以检查它们是否相同:
最后一点:我完全知道这个编辑包含了很多新内容 信息,尤其是来自Numpy区域的信息。 但不要因为新概念的“雪崩”而感到害怕。 把每一个新的或鲜为人知的问题,一个接一个, 并在网上搜索进一步的解释。在
相关问题 更多 >
编程相关推荐