繁体   English   中英

用Pandas进行贪婪设置掩盖的最快方法是什么?

[英]What is the fastest way to do greedy set cover with Pandas?

这个问题与贪婪集覆盖问题并不完全相同,但是它们具有相同的想法。

给定一个熊猫数据帧df1,其中一列df ['s']由一组df2键组成:

import numpy as np
import pandas as pd
>>> df = pd.DataFrame(np.array([set([1,3,5]), set([1,3,5,6]), set([2,3,4,12]), set([1,3,7]), set([1,15,11]), set([1,16]), set([16])]),columns=['s'])
>>> df
                    s
0      set([1, 3, 5])
1   set([1, 3, 5, 6])
2  set([12, 2, 3, 4])
3      set([1, 3, 7])
4    set([1, 11, 15])
5        set([1, 16])
6           set([16])
        ...

>>> df2 = pd.DataFrame(np.array([[1,2,3,3,3,6,4,8,9,10,11,12,13,14,15,16,5,7],[2.,1.,3.,2.,1.,2.,3.,1.,1.,1.,1.,1.,1.,1.,1.,16.,1.,1.]]).T,columns=['key', 'value'])
>>> df2
    key  value
0     1      2
1     2      1
2     3      3
3     3      2
4     3      1
5     6      2
6     4      3
7     8      1
8     9      1
9    10      1
10   11      1
11   12      1
12   13      1
13   14      1
14   15      1
15   16     16
16    5      1
17    7      1

    ...

上面的数据帧df2可以包含重复的键。 我们选择最后一个。 例如,为上面的键“ 3”选择值“ 1.0”。

我想找到df ['s]的前六行,这些行可以最大程度地求和其对应键的值之和,并按其值贡献对新数据帧的行进行排序。 最快的方法是什么?

对于上面给定的数据集,结果数据帧的前两行应为

df3:
    set([1,16])
    set([12,2,3,4])
    ...

上面的第二个不是set([16]),因为set([1,16])中已经包含“ 16”,并且set([16])的相加值为零。

按集合键的相应值的总和排序。

更新时间:

为了简化此问题,让我们考虑df2仅包含唯一键。 而且可以根据安德鲁的技巧轻松修复。

假设您没有太多键,则可以将集合列表表示为稀疏矩阵,每个键都有一列。

In [29]: df = pd.DataFrame([{1:1,3:1,5:1}, {1:1,3:1,5:1,6:1}, {2:1,3:1,4:1,12:1}, {1:1,3:1,7:1}, {1:1,15:1,11:1}, {9:1}, {16:1}]).fillna(0)

In [30]: df
Out[30]: 
   1   2   3   4   5   6   7   9   11  12  15  16
0   1   0   1   0   1   0   0   0   0   0   0   0
1   1   0   1   0   1   1   0   0   0   0   0   0
2   0   1   1   1   0   0   0   0   0   1   0   0
3   1   0   1   0   0   0   1   0   0   0   0   0
4   1   0   0   0   0   0   0   0   1   0   1   0
5   0   0   0   0   0   0   0   1   0   0   0   0
6   0   0   0   0   0   0   0   0   0   0   0   1

然后将您的权重表示为一个系列,按键索引:

In [37]: weights = df2.drop_duplicates('key', keep='last').set_index('key')['value']

然后加权并求和:

In [40]: totals = (df * weights).sum(axis=1)

In [41]: totals
Out[41]: 
0     4
1     6
2     6
3     4
4     4
5     1
6    16
dtype: float64

然后只需找到前6行:

In [55]: top6 = totals.order(ascending=False).head(6)

In [56]: top6
Out[56]: 
6    16
2     6
1     6
4     4
3     4
0     4
dtype: float64

您可以使用返回到稀疏矩阵的索引来恢复这些集合是:

In [58]: df.ix[top6.index]
Out[58]: 
   1   2   3   4   5   6   7   9   11  12  15  16
6   0   0   0   0   0   0   0   0   0   0   0   1
2   0   1   1   1   0   0   0   0   0   1   0   0
1   1   0   1   0   1   1   0   0   0   0   0   0
4   1   0   0   0   0   0   0   0   1   0   1   0
3   1   0   1   0   0   0   1   0   0   0   0   0
0   1   0   1   0   1   0   0   0   0   0   0   0

您可能不喜欢这种方法,但我要指出的是,像集合这样的数据结构框架,而不是图元,因为元素并不是特别熊猫风格,因此建议对问题进行一些翻译。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM