【问题标题】:Getting empty CSV in python在python中获取空的CSV
【发布时间】:2020-01-04 20:57:36
【问题描述】:

我编写了一段代码,用于比较来自两个 csv 的数据并将最终输出写入一个新的 csv。问题是除了标题之外没有其他内容被写入 csv。下面是我的代码,

import csv


data_3B = open('3B_processed.csv', 'r') 
reader_3B = csv.DictReader(data_3B)

data_2A = open('2A_processed.csv', 'r') 
reader_2A = csv.DictReader(data_2A)

l_3B_2A = [["taxable_entity_id", "return_period", "3B", "2A"]]

for row_3B in reader_3B:
    for row_2A in reader_2A:
        if row_3B["taxable_entity_id"] == row_2A["taxable_entity_id"] and row_3B["return_period"] == row_2A["return_period"]:
            l_3B_2A.append([row_3B["taxable_entity_id"], row_3B["return_period"], row_3B["total"], row_2A["total"]])


with open("3Bvs2A_new.csv", "w") as csv_file:
    writer = csv.writer(csv_file)

    writer.writerows(l_3B_2A)

csv_file.close()

我该如何解决这个问题?

编辑: 2A_processed.csv 样本:

taxable_entity_id,return_period,total
2d9cc638-5ed0-410f-9a76-422e32f34779,072019,0
2d9cc638-5ed0-410f-9a76-422e32f34779,062019,0
2d9cc638-5ed0-410f-9a76-422e32f34779,082019,0
e5091f99-e725-44bc-b018-0843953a8771,082019,0
e5091f99-e725-44bc-b018-0843953a8771,052019,41711.5
920da7ba-19c7-45ce-ba59-3aa19a6cb7f0,032019,2862.94
410ecd0f-ea0f-4a36-8fa6-9488ba3c095b,082018,48253.9

3B_处理过的样本:

taxable_entity_id,return_period,total
1e5ccfbc-a03e-429e-b79a-68041b69dfb0,072017,0.0
1e5ccfbc-a03e-429e-b79a-68041b69dfb0,082017,0.0
1e5ccfbc-a03e-429e-b79a-68041b69dfb0,092017,0.0
f7d52d1f-00a5-440d-9e76-cb7fbf1afde3,122017,0.0
1b9afebb-495d-4516-96bd-1e21138268b7,072017,146500.0
1b9afebb-495d-4516-96bd-1e21138268b7,082017,251710.0

【问题讨论】:

  • 你试过用熊猫数据框做这个吗?
  • 您确定您的列表l_3B_2A 包含您要收集的所有数据吗? if 的情况在我看来很可疑。大胆猜测,taxable_entity_idreturn_period 中的一个键在末尾包含换行符,这就是为什么字符串的相等比较永远不起作用的原因。
  • @BillyBonaros 我如何使用熊猫来做到这一点?我不是很擅长..
  • @Arne,我不确定.. 这两个键的末尾没有换行符.. 我比较的两个 csv 是使用 python 生成的。我正在添加一个示例。
  • @MohnishM 如果您在 if 之后编写 else 条件并在其中打印 row_3B 和 row_2A,您可能会明白为什么即使您认为应该输入 if 条件,您也永远无法进入。跨度>

标签: python csv


【解决方案1】:

代码中的csv.DictReader 对象只能读取文件一次,因为它们是从文件对象(使用open 创建的)中读取的。因此,第二次及以后通过外循环,内循环没有运行,因为没有更多的row_2Ain reader_2A——第一次后读者在文件末尾。

最简单的解决方法是先将每个文件读入一个列表。我们可以创建一个辅助函数来处理这个问题,并确保文件正确关闭:

def lines_of_csv(filename):
    with open(filename) as source:
        return list(csv.DictReader(source))

reader_3B = lines_of_csv('3B_processed.csv')
reader_2A = lines_of_csv('2A_processed.csv')

【讨论】:

  • 在我编写此脚本的早期尝试之一中,我做到了。但这需要很长时间,因为一个 CSV 中有 100 万行,而另一个 CSV 中有 50 万行。
  • 是的,那么你需要一个更好的算法。我可以展示如何做到这一点,但使用实际数据库会简单得多。
  • 我无法直接连接到数据库,因为有 5 分钟超时并且 ssh 隧道转发到位。我在这里问过这个问题..stackoverflow.com/questions/57737400/… 还没有收到任何有用的回复..
  • 既然您大概已经在本地下载了数据库数据为 csv,也许您可​​以重建数据库的本地副本?
  • 嘿,我已经解决了这个问题,不再处理这个问题了。也许我可以那样做.. 无论如何感谢您的建议!
【解决方案2】:

我将您的代码放入文件 test.py 并创建了测试文件来模拟您的 csvs。

$ python3 ./test.py
$ cat ./3Bvs2A_new.csv 
taxable_entity_id,return_period,3B,2A
1,2,3,2
$ cat ./3B_processed.csv 
total,taxable_entity_id,return_period,3B,2A
3,1,2,3,4
3,4,3,2,1

$ cat ./2A_processed.csv 
taxable_entity_id,return_period,2A,3B,total
1,2,3,4,2
4,3,2,1,2

因此,您可以看到列的顺序无关紧要,因为它们正在使用 dict 阅读器正确访问,如果第一行匹配,则您的代码有效,但之后第二个 csv 文件中没有行处理第一个文件的第一行。如果 taxable_entity_id 和 return_period 元组值,我建议制作一个字典,通过将总计添加到字典中来处理第一个 csv 文件,然后运行第二个并查找它们。

row_lookup = {}
for row in first_csv:
    rowLookup[(row['taxable_entity_id'], row['return_period'])] = row['total']

for row in second_csv:
    if (row['taxable_entity_id'],row['return_period']) in row_lookup.keys():
        newRow = [row['taxable_entity_id'], row['return_period'], row['total'] ,row_lookup[(row['taxable_entity_id'],row['return_period']] ]

当然,只有当 taxable_entity_ids 和 return_periods 对始终唯一时才有效...如果不知道您的任务的确切性质和 csv 的完整格式,很难确切地说您应该做什么。

【讨论】:

  • 这并没有解决读取文件的问题,而且它也误解了循环在原始代码中的工作方式。但是,查找字典的建议仍然是一个很好的,并且是使其有效工作的关键。
  • 等我明白你在说什么。我错过了循环的嵌套。因此,他在第二个 csv 中的第一行与第一行中的任何内容都不匹配,因此他没有得到任何输出。我正专注于试图弄清楚他想做什么并且没有发表评论的声誉......
  • @David.. 兄弟,你救了我的命。您的方法将我的执行时间从几天缩短到几秒钟。谢谢!
  • 很高兴为您提供帮助。只要确保这是正确的输出。如果实体 id 和返回周期对在每个文件中只出现一次,那么应该没问题。如果它们可以多次出现(我不确定您对实体 ID 表示哪种实体),那么字典将仅保存第一个 CSV 和返回期中具有特定 ID 的最后一条记录,您将得到第二个文件中每对一行与遍历列表的所有组合的行。不过,我确实觉得这是正确的。
【解决方案3】:

如果数据框的大小像这样,您可以使用 pandas 执行此操作:

reader_3B=pd.read_csv('3B_processed.csv')
reader_2A=pd.read_csv('2A_processed.csv')

l_3B_2A=row_3B[(row_3B["taxable_entity_id"] == row_2A["taxable_entity_id"])&(row_3B["return_period"] == row_2A["return_period"])]

l_3B_2A.to_csv('3Bvs2A_new.csv') 

【讨论】:

  • 一个 CSV 有大约一百万行,而另一个有 50 万行。
猜你喜欢
  • 2014-04-13
  • 1970-01-01
  • 2021-04-12
  • 2011-03-21
  • 2021-11-23
  • 1970-01-01
  • 2012-11-20
  • 2022-06-13
  • 2020-11-07
相关资源
最近更新 更多