【问题标题】:Set intersection with two conditions设置两个条件的交集
【发布时间】:2014-09-05 03:34:16
【问题描述】:

我在 CSV 文件中有以下数据集。

Entity_A,Category1,Rule1,1990,1992,2
Entity_B,Category1,Rule1,1990,1993,3
Entity_C,Category2,Rule2,1992,1994,2
Entity_A,Category2,Rule2,1992,1993,1
Entity_B,Category2,Rule2,1992,1993,1
Entity_C,Category1,Rule1,1990,1994,4

它基本上说:Entity_A 在 1992 年实施了 Rule1,而 Rule1 是在 1990 年提出的。实施时间为 2 年(减去 1992-1990)。

我已经实现了一个函数,它可以给出两个状态之间有多少共同规则。这是代码:

print set(item[2] for item in L if item[0]=='Entity_A').intersection([item[2] for item in L if item[0]=='Entity_B']) #this gives the common rules between A and B. In this case 2. 

我想实现以下内容: 假设 Entity_A 在 1992 年实施了一条规则,那么我想知道 Entity_B 在 A 之后实施了多少条规则。在上述数据集中,答案将是 Entity_A -- Entity_B = 1,因为 B 在 A 之后实施了 1 条规则实施了该规则。 基本上 B 跟随 A。

在这种情况下,我需要比较A的item[5]和B的item[5]。如何在集合计算中比较它们并计算结果?我基本上想打印以下内容:

Entity_A, Entity_B, 1 --> 这是 A 和 B 之间的关系,其中 B 在一条规则中遵循 A。

Entity_A, Entity_C, 2 --> C 遵循 a in two rule implementation

【问题讨论】:

    标签: python csv set conditional intersection


    【解决方案1】:
    set(item[2] for item in L if (item[0]=='Entity_A' and int(item[5]) == k)).intersection([item[2] for item in L if (item[0]=='Entity_B' and int(item[5]) > k)]) #k is a counter for item[5]
    

    【讨论】:

    • 请在您的代码中添加一些有意义的解释,以便原始发布者能够更好地理解您的答案如何解决他的问题。
    【解决方案2】:
    def numRulesBImplementedAfterA(a, b, L):
        a_date_map = {item[1] : item[3] for item in L if item[0] == a}
        count = 0
        for item in L:
            if item[0] != b:
                continue
            b_rule = item[1]
            b_implemented_date = item[3]
            a_implemented_date = a_date_map.get(b_rule)
            if a_implemented_date is None:
                continue
            if b_implemented_date > a_implemented_date:
                count += 1
        return count
    

    【讨论】:

    • 打印 numRulesBImplementedAfterA('Entity_A', 'Entity_B', [['Entity_A', 'Rule1', '1990', '1992', '2'], ['Entity_B', 'Rule1' , '1990', '1993', '3'], ['Entity_C', 'Rule2', '1992', '1994', '2'], ['Entity_A', 'Rule2', '1992', ' 1993', '2'], ['Entity_B', 'Rule2', '1992', '1993', '2']]) # 对我来说,这给出了正确答案 1。你会发生什么?我认为 csv 读取步骤可能有问题。
    【解决方案3】:

    您无法真正将这些与集合表示法进行比较,因为您正在构建没有必要信息的集合。如果你想构建一个在 Entity_B 之后实施的规则 Entity_A 的集合,你将不得不做更多的工作:

    a_impl = [(x[1], x[3]) for x in L if x[0] == 'Entity_A'] # (rule_number, year_implemented)
    b_impl = [(x[1], x[3]) for x in L if x[0] == 'Entity_B'] # same for b
    b_impl_after_a = filter(lambda k: k[0] == k[2] and k[1] < k[3], [x+y for x in a_impl for y in b_impl])
    

    这不是我的想法,所以你可能可以更聪明地做到这一点,但它确实有效。 a_impl 包含 Entity_A 实现的所有规则的两个元组,以及它们何时实现,b_impl 和 Entity_B 也是如此。

    [x+y for x in a_impl for y in b_impl] 为所有这些规则构造一个叉积,过滤器只提取规则相同且 Entity_A 在 Entity_B 之前实现的那些。

    如果您只想要规则的名称,您可以遍历过滤器:

    b_impl_after_a = [x[0] for x in b_impl_after_a]
    

    【讨论】:

    • 我试过了,但没有给出正确的答案。我在上面提到的相同数据集上对其进行了测试。
    • In [148]: list(b_impl_after_a) Out[148]: [('Rule1', '1992', 'Rule1', '1993')] 你确定吗?这是我从复制粘贴我的答案中得到的......
    • k[1]
    • 这是我的 L 的样子: In [49]: L Out[49]: [['Entity_A', 'Rule1', '1990', '1992', '2'], ['Entity_B','Rule1','1990','1993','3'],['Entity_C','Rule2','1992','1994','2'],['Entity_A',' Rule2', '1992', '1993', '2'], ['Entity_B', 'Rule2', '1992', '1993', '2']] 所以本质上是列表列表。如果您的数据不同,您可能需要稍作更改。
    • 备案,k[1]是Entity_A实施规则k[0]的年份,k[3]是Entity_B实施规则k[2]的年份。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 2016-01-20
    相关资源
    最近更新 更多