【问题标题】:Python - Find, match, sort and append based on unique valuesPython - 根据唯一值查找、匹配、排序和追加
【发布时间】:2017-12-05 02:15:15
【问题描述】:

我有一个 CSV 文件,其中包含指定帐户链接结构的两列。 我遇到的问题是这些链接中的每一个都有一个双重反向条目。

例子

Column1 Column2
12513   52188
52188   12513

我还遇到的另一个问题是,可能有更多条目指定与同一帐号的另一个链接

Column1 Column2
12513   52188
52188   12513
52188   19922
19922   52188
19922   12812
12812   19922
18216   59888
59888   18216
3856   59888
59888   3856

正如您所见,所有账户都以某种方式相互关联,我正在寻找的输出应该创建一个与从账户相关联的主账户(可能是价值最低的账户),并删除双重反向输入.

以上数据的示例输出:

Column1 Column2
12513   52188
12513   19922
12513   12812
3856    59888
3856    18216

该文件包含大约 20,000 行,其中, 请注意,主帐户不只有一个。

【问题讨论】:

  • 你预期的输出不清楚
  • git clone https://github.com/NiallCosgrove/kayboxa
  • 它现在在 github 上,以避免复制/粘贴错误。我用 20000 对随机数对其进行了测试,花了一刻钟。让我知道你的进展情况
  • 这非常有效,非常感谢您的帮助。如果您可以为刚开始使用 python 的人推荐任何好的阅读材料,我将不胜感激。
  • 再次感谢您,我早些时候尝试过,但没有足够的代表投票。现在我做到了,希望你能达到 1k。节日快乐。

标签: python csv data-mining


【解决方案1】:

所以问题是:
给定表格中的数据集

1,2
1,3
1,4
3,1
6,5
5,7

识别链 1 -> 2 -> 3 -> 45 -> 6 -> 7 并将它们输出为

1,2
1,3
1,4
5,6
5,7

这是一个在 python 中工作的解决方案。 (节日快乐)

要运行它,请使用python thisfile.py yourdata.csv > output.csv

当然,您需要安装 python3。 代码中有很多 cmets。我根本没有考虑效率,所以把水壶打开 - 大约需要 15 分钟左右才能完成。

如果您希望它更快,它的 list.append() 调用会花费时间。使用 numpy 可能会加快速度,但我不想添加额外的依赖项。

如果您有任何问题,请告诉我。

您的示例数据的输出是:

3856 , 18216
3856 , 59888
12513 , 12812
12513 , 19922
12513 , 52188
import csv
import sys


def flatten(l):
    return list(set([item for subl in l for item in subl]))

def main():
    # read the csv                                                                                      
    raw_data = []
    with open(sys.argv[1], 'r') as so_data:
        lst = csv.reader(so_data)
        for row in lst:
            raw_data.append(row)

        data = []
        for i in raw_data:
            data.append([int(i[0].strip()), int(i[1].strip())])

        #set keys to uniq elements from col1 and col2                                                   
        keys1 = list(set([i[0] for i in data]))
        keys2 = list(set([i[1] for i in data]))
        keys = list(set(keys1 + keys2))

        # find the subchains for each key                                                               
        subchains = {}
        for key in keys:
            found = [k for k in data if key in k]
            found = flatten(found)
            subchains[key] = found

        # This is the tricky bit                                                                        
        # we need to follow each element of the subchains looking                                       
        # for new links - we are done for a key when the list doesn't grow                              
        chain, links = [], []
        chain_dict = {}
        for key in keys:
            links.append(subchains[key])
            links = flatten(links)
            done = False
            size = len(links)
            while not done:
                for i in links:
                    # find subchain for i                                                               
                    for e in subchains[i]:
                        chain.append(e)
                        chain = list(set(chain))
                        chain.sort()
                if len(chain) > size:
                    done = False
                    size = len(chain)
                else:
                    done = True
                    chain_dict[key] = chain
                    chain, links = [], []

        # shorter chains will now be subsets of longer ones                                             
        # and those can be discarded                                                                    
        remove_list = []
        for i in keys:
            for j in keys:
                if set(chain_dict[j]) < set(chain_dict[i]):
                    remove_list.append(j)

        remove_list = list(set(remove_list))
        for i in remove_list:
            del chain_dict[i]

        # remove duplicate values from dict                                                             
        # it doesn't matter which key we remove                                                         
        # since we only output from value                                                               
        result = {}
        for key, value in chain_dict.items():
            if value not in result.values():
                result[key] = value

        # now output as per OP's request                                                                
        for k, v in result.items():
            v.sort()
            for i in v[1:]:
                print(v[0], ",", i)

if __name__ == '__main__':
    main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 2016-08-11
    • 2021-12-25
    • 1970-01-01
    • 2019-01-13
    相关资源
    最近更新 更多