【问题标题】:Used CSV DictReader to read in rows and filter based on lat long ranges使用 CSV DictReader 读取行并根据 lat 长范围进行过滤
【发布时间】:2018-02-21 20:31:22
【问题描述】:

我有 179 GB 以下稀疏数据:

id    lat    long   var1    var2    var3
1     52.1   0.07    A       
2     58.3   5.78            C  
3     46.5  -8.32                    E 

我想读入数据并过滤,以便只保留某些经纬度坐标之间的行。在此表示中,纬度的示例范围是 51.0 到 59.0,经度的范围是 -1.0 到 6.0

到目前为止,我只有一个 CSV 字典阅读器和一个不起作用的字典理解:

with open("test_data.csv", 'r', encoding="Latin-1") as f:
    reader = csv.DictReader(f)
    rows = [row for row in reader if row['lat'] >= 51.0 if row['lat'] <= 59.0 if row['long'] >= -1.0 if row['long'] <= 6.0]
    print(rows)

目前我得到一个 TypeError: Unorderedable types: str() >= int() 这可能是因为 DictReader 将事物作为字符串引入,它们需要是整数值。我不确定如何将 int() 插入到 dict 理解中。

最终,我希望输出选择以下数据:

id    lat    long   var1    var2    var3
1     52.1   0.07    A       
2     58.3   5.78            C  

我对字典的格式感到矛盾,因为我想在之后将数据写回 csv。

【问题讨论】:

  • 你说它“不起作用”是什么意思?
  • 我认为这是因为我需要将 lat long 转换为 int,因为 DictReader 将它们作为字符串引入。
  • 我不是说 why 不工作,我的意思是 如何 不工作。你有错误吗?输出不正确吗?发生了什么让您认为它“不起作用”?
  • @ason​​gtoruin 我已经修改了问题
  • 您应该将它们作为浮点数进行比较,因为没有整数值。您可以使用float(row['lat']) 强制转换为浮动。此外,关于您的标签,您使用的是列表理解,尽管它是一个字典列表。

标签: python dictionary list-comprehension


【解决方案1】:

除非您遇到内存问题,否则pandas 应该能够为您完成这项工作。如果您还没有安装pandas,则可能需要先安装,但使用pip 应该很容易(并且是一个很棒的软件包)

import pandas as pd

df = pd.read_csv('test_data.csv')

filtered = df[(df['lat'].between(51.0, 59.0, inclusive=True)) &
              (df['long'].between(-1.0, 6.0, inclusive=True))]

filtered.to_csv('filtered_test_data.csv')

如果您确实遇到内存问题,使用chunksize 参数可以让您仅将一定数量的行读入内存。由于您的过滤是每行独立的,我们可以按块应用此过滤并将它们全部组合起来:

import pandas as pd

chunks = pd.read_csv('test_data.csv', chunksize=1000000)

filtered = pd.concat([df[(df['lat'].between(51.0, 59.0, inclusive=True)) &
                         (df['long'].between(-1.0, 6.0, inclusive=True))]
                      for df in chunks])

filtered.to_csv('filtered_test_data.csv')

如果这仍然不起作用,您可以尝试保存每个块并仅在最后合并:

import pandas as pd

chunks = pd.read_csv('test_data.csv', chunksize=1000000)

i = 0
for df in chunks:
    filtered = df[(df['lat'].between(51.0, 59.0, inclusive=True)) &
                  (df['long'].between(-1.0, 6.0, inclusive=True))]
    filtered.to_csv('chunk_{}.csv'.format(i))
    i += 1

final = pd.concat(pd.read_csv('chunk_{}.csv'.format(j)) for j in range(i))
final.to_csv('final.csv')

【讨论】:

  • 在尝试运行它一夜之后,它遇到了内存困难并崩溃了。有非熊猫版本吗?这就是我最初要求 CSV DictReader 答案的原因,因为 Pandas 通常不能很好地处理大型数据集(这是 179GB)。
  • @ThirstforKnowledge 查看编辑。熊猫可以处理很多,我不会这么快就把它写下来!
  • 虽然实际上,它仍然可能在 179gb 上崩溃。
  • 谢谢,我会试试块大小并确认答案是否有效!
  • @ThirstforKnowledge 这将取决于有多少记录符合您的条件 - 使用 chunksize 可以让 pandas 遍历文件,因此在任何时候它都会有当前块加上找到的匹配项在内存中的任何以前的块中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-06
  • 2020-02-15
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多