【问题标题】:Finds all rows fitting to combinatorial condition查找适合组合条件的所有行
【发布时间】:2017-11-19 13:40:49
【问题描述】:

我正在寻找使用 python\excel\sql\google 表格执行此操作的最佳方法 - 我需要从 n 个值的列表中找到适合 k 个值的所有行。

例如,我有一张名为 Animals 的表:

| Name     | mammal | move   |  dive |
+----------+--------+--------+-------+
| Giraffe  |  1     |    1   |   0   |
| Frog     |  0     |    1   |   1   |
| Dolphin  |  1     |    1   |   1   |
| Snail    |  0     |    1   |   0   | 
| Bacteria |  0     |    0   |   0   | 

我想写一个函数 foo,它的行为是这样的:

foo(布尔值元组,最小匹配)

foo((1,1,1),3) -> Dolphin
foo((1,1,1),2) -> Giraffe, Dolphin, Frog
foo((1,1,1),1) -> Giraffe, Dolphin, Frog, Snail
foo((1,1,0),2) -> Giraffe, Dolphin
foo((0,1,1),2) -> Dolphin, Frog
foo((0,1,1),1) -> Giraffe, Dolphin, Frog, Snail
foo((1,1,1),0) -> Giraffe, Dolphin, Frog, Snail, Bacteria 

你认为最好的方式是什么?

【问题讨论】:

  • sql 不在 ('python', 'excel', 'google sheet')
  • 我修好了,sql也很好
  • foo((1,1,0),2) 怎么只有长颈鹿,海豚?不会有蜗牛吧?
  • foo((1,1,0),2) 寻找所有哺乳动物并移动
  • 只有海豚和青蛙会移动和潜水 - 这是对 foo((0,1,1),2) -> 海豚,青蛙的回复,但海豚和蜗牛都是 1.not a哺乳动物和蜗牛可以 2.move。 2 场比赛。

标签: python sql excel pandas google-sheets


【解决方案1】:

这是一个纯 Python 3 解决方案。

data = [
    ('Giraffe',  1, 1, 0),
    ('Frog',     0, 1, 1),
    ('Dolphin',  1, 1, 1),
    ('Snail',    0, 1, 0),
    ('Bacteria', 0, 0, 0),
]

probes = [
    ((1, 1, 1), 3),
    ((1, 1, 1), 2),
    ((1, 1, 1), 1),
    ((1, 1, 0), 2),
    ((0, 1, 1), 2),
    ((0, 1, 1), 1),
    ((1, 1, 1), 0),
]

def foo(mask, minmatch):
    for name, *row in data:
        if sum(u & v for u, v in zip(mask, row)) >= minmatch:
            yield name

for mask, minmatch in probes:
    print(mask, minmatch, *foo(mask, minmatch))

输出

(1, 1, 1) 3 Dolphin
(1, 1, 1) 2 Giraffe Frog Dolphin
(1, 1, 1) 1 Giraffe Frog Dolphin Snail
(1, 1, 0) 2 Giraffe Dolphin
(0, 1, 1) 2 Frog Dolphin
(0, 1, 1) 1 Giraffe Frog Dolphin Snail
(1, 1, 1) 0 Giraffe Frog Dolphin Snail Bacteria

在 Python 3.6.0 上测试。它使用了一些旧版本中不可用的语法,但很容易适应它以使用旧语法。


此变体可在较旧版本的 Python 上运行。在 Python 2.6.6 上测试。

from __future__ import print_function

data = [
    ('Giraffe',  1, 1, 0),
    ('Frog',     0, 1, 1),
    ('Dolphin',  1, 1, 1),
    ('Snail',    0, 1, 0),
    ('Bacteria', 0, 0, 0),
]

probes = [
    ((1, 1, 1), 3),
    ((1, 1, 1), 2),
    ((1, 1, 1), 1),
    ((1, 1, 0), 2),
    ((0, 1, 1), 2),
    ((0, 1, 1), 1),
    ((1, 1, 1), 0),
]

def foo(mask, minmatch):
    for row in data:
        if sum(u & v for u, v in zip(mask, row[1:])) >= minmatch:
            yield row[0]

for mask, minmatch in probes:
    matches = list(foo(mask, minmatch))
    print(mask, minmatch, matches)

输出

(1, 1, 1) 3 ['Dolphin']
(1, 1, 1) 2 ['Giraffe', 'Frog', 'Dolphin']
(1, 1, 1) 1 ['Giraffe', 'Frog', 'Dolphin', 'Snail']
(1, 1, 0) 2 ['Giraffe', 'Dolphin']
(0, 1, 1) 2 ['Frog', 'Dolphin']
(0, 1, 1) 1 ['Giraffe', 'Frog', 'Dolphin', 'Snail']
(1, 1, 1) 0 ['Giraffe', 'Frog', 'Dolphin', 'Snail', 'Bacteria']

【讨论】:

  • @SuperMario 这是相当新的语法,仅在最新版本的 Python 中可用。基本上,name, *row 拆分当前的data 元组,因此第一个元组项被分配给name,其余的元组被分配给row。这是一个更简单的示例:a, *b = (1,2,3)1 放入 a 并将 (2,3) 放入 b。同样,*a, b=(4,5,6)(4,5) 放入a 并将6 放入b
  • 它有名字吗?
  • @SuperMario 是的。 :) 它叫做Extended Iterable Unpacking。在this Stack overflow page 上提到了它,还有很多其他的元组解包变体。
【解决方案2】:

如果表是 pandas 数据框:

def foo(df, val, n_match):
    results = []
    for r in  df.values:
        if sum(val & r[1:]) >= n_match:
            results.append(r[0])
    print("foo(%s), %d -> %s") % (val, n_match, ' '.join(results))

【讨论】:

    【解决方案3】:

    我会尝试将 python 与 pandas 一起使用

    假设“名称”列是熊猫索引:

    def foo(df, bool_index, minimum_matches):
        picked_column_index = [ idx for (idx, i) in enumerate(bool_index) if i] # select where "1" is
        picked_df = df.iloc[:, picked_column_index] #select column by location
        matched_row_bool = picked_df.sum(axis=1) >= minimum_matches
        return picked_df[matched_row_bool].index.tolist()
    

    df 是从表中读取的 pandas 数据帧(动物) 也许:

    df = pandas.read_csv('animials_csv_file_path')
    

    df = pandas.read_excel('animials_xls_file_path')
    

    它将返回一个包含匹配名称的列表

    【讨论】:

    • 这个函数中的df是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    相关资源
    最近更新 更多