【问题标题】:Building a map for large datasets为大型数据集构建地图
【发布时间】:2016-04-20 00:15:26
【问题描述】:

我有一个非常大的文件,它有两列,大小约为 10GB:

A  B
1  2
3  7
1  5
6  5
9  8

基本上,我想从这个文件中创建一个类似地图的结构,如下所示:

{{1 -> 2,5},{3->7}, {6->5}, {9->8}}

目标是编写一个函数来计算受删除键影响的唯一值的百分比。例如,在上面的例子中,如果我删除键,1, 2/4 的值会受到影响。如果我同时删除 1 和 6,则 2/4 的值会受到影响。问题是这个map结构会占用太多内存。有没有更有效的替代方法?我认为您需要一张地图来跟踪重复项。您需要知道哪些键已被删除,以免重复计算。这是我的初始代码:

with open("C:/Users/XX/Desktop/Train.tsv") as f:
    counter = 0
    for line in f:
      #split line into key and value
      #add key into set
      #if set does not contain key
         #create new key
         #add list for this key
         #append value to this list
      #else
         #append value to already existing list for that key

这是我在运行 Alexander 的代码后得到的错误消息:不确定 KeyError 293 是什么意思

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-22-73145e080824> in <module>()
      7     for line in f:
      8         key, value = line.split()
----> 9         if value not in dd[key]:
     10             dd[key].append(value)
     11         counter = counter+1

KeyError: '293'

【问题讨论】:

  • 您是否期望许多值只出现在一个键上?您可以通过仅跟踪键的数量而不是确切的值是什么来节省一些内存。
  • 这两列的实际范围是多少?它们保证是整数吗?小整数?字符?
  • 两者的类型都应该是整数。另外,如果我不知道确切的值并且只知道每个键的频率,则很难获得覆盖范围,因为我会重复计算,因为不同的键可能具有相同的值。
  • 如果给定键的值重复怎么办?你想保留两者,还是只保留一组?
  • 这些整数的大小是否有限制?您可以通过使用array.array 数组来存储与键关联的值来节省内存。

标签: python pandas anaconda


【解决方案1】:

这样的?

#!python3

from collections import defaultdict

AB_map = defaultdict(set)
Values = set()

with open('train.tsv') as infile:
    headers = next(infile)
    for line in infile:
        if not line.strip():
            continue
        a,b = map(int, line.split())
        AB_map[a].add(b)
        Values.add(b)

print("# of keys:", len(AB_map.keys()))
print("# of values:", len(Values))

def impact_of_deletion(keylist):
    values_impacted = set([])
    for key in keylist:
        values_impacted.update(AB_map[key])
    return values_impacted

for hyp in ((1,), (1,6)):
    print("Deleting", hyp, "would impact:", len(impact_of_deletion(hyp)))

【讨论】:

    【解决方案2】:

    您可以为此使用 defaultdict,我们将其设置为自动为每个键分配一个空列表:

    from collections import defaultdict
    
    filename = "C:/Users/XX/Desktop/Train.tsv"
    dd = defaultdict(list)
    with open(filename) as f:
        for line in f:
            key, value = line.split(',')  # Assuming comma delimited.
            if value not in dd[key]:  # If you only want to retain unique values.
                dd[key].append(value)
    

    【讨论】:

    • 这对内存问题没有帮助。
    • 应该的。首先,您逐行而不是批量读取文件。其次,您正在保存每个键的唯一值,而不是所有键。如果不将结果保存到数据库或文件中,就没有什么可以做的了。
    • @Alexander @zorny 我认为应该是dd = defaultdict(list)。我想这解决了KeyError 的问题。
    • 是的!很抱歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    相关资源
    最近更新 更多