在python中迭代CSV文件以查找带有前导空格的标题
我正在使用一个包含歌曲及其所有者属性的大型csv文件。每个歌曲记录都是自上而下写的,每个标题下都有相关的作者和出版商的名字。因此,一首给定的歌曲可能由4-6行组成,这取决于有多少作者/出版商控制它(下面是标题行的示例): 我目前正在尝试循环遍历整个文件,以提取包含前导空格的所有歌曲标题(例如,“song title”)。以下是我当前使用的代码:在python中迭代CSV文件以查找带有前导空格的标题,python,python-3.x,csv,Python,Python 3.x,Csv,我正在使用一个包含歌曲及其所有者属性的大型csv文件。每个歌曲记录都是自上而下写的,每个标题下都有相关的作者和出版商的名字。因此,一首给定的歌曲可能由4-6行组成,这取决于有多少作者/出版商控制它(下面是标题行的示例): 我目前正在尝试循环遍历整个文件,以提取包含前导空格的所有歌曲标题(例如,“song title”)。以下是我当前使用的代码: import csv import re with open('output/sws.txt', 'w') as sws: with open
import csv
import re
with open('output/sws.txt', 'w') as sws:
with open('data/ascap_catalog1.csv', 'r') as ac:
ascap = csv.reader(ac, delimiter=',')
ascap = list(ascap)
for row in ascap:
for strings in row:
if re.search('\A\s+', strings):
row = str(row)
sws.write(row)
sws.write('\n')
else:
continue
由于我正在处理的这个csv文件的大小(~2GB),遍历并生成结果文件需要相当长的时间。然而,根据我得到的结果,似乎带前导空格的歌曲标题都聚集在文件的开头。这些歌曲全部列出后,将显示不带前导空格的普通歌曲
有没有办法让这段代码在时间上更有效率?我尝试在每个for和if语句之后使用一些break
s,但根据使用的数量,它要么根本不会影响语句,要么中断得太快,无法捕获任何行
我还尝试将其包装在函数中并实现return
,但是,出于某种原因,代码似乎只遍历第一行(不包括标题行,我将跳过它)
非常感谢您的时间,您可以使用字典查找每首歌曲并将其所有相关值分组:
from collections import defaultdict
import csv, re
d = defaultdict(list)
count = 0 #count needed to remove the header, without loading the full data into memory
with open('filename.csv') as f:
for a, *b in csv.reader(f):
if count:
if re.findall('^\s', a):
d[a].append(b)
count += 1
list(ascap)
对你没有任何好处reader
对象是其内容的迭代器,但在需要时才将其全部加载到内存中。直接迭代读取器
对象即可
对于每一行,只需选中行[0][0].isspace()
。这将检查第一个条目的第一个字符,这是确定某个内容是否以空格开头所需的全部内容
with open('output/sws.txt', 'w', newline="") as sws:
with open('data/ascap_catalog1.csv', 'r', newline="") as ac:
ascap = csv.reader(ac, delimiter=',')
for row in ascap:
if row and row[0] and row[0][0].isspace():
print(row, file=sws)
您还可以处理输出,比如在最后写入行之前将要保留在列表中的所有行保存起来。如果所有前导的空白名称都排在第一位,听起来您的输入可能会被排序。如果是这种情况,您可以添加
else:break
跳过文件的其余部分。以下是一些您可以改进的地方:
- 直接将对象用作迭代器,而不创建中间列表。这将节省您的计算时间和内存
- 仅检查行中的第一个值(即标题),而不是全部
- 删除不必要的
子句else
import csv
import re
from itertools import takewhile
with open('data/ascap_catalog1.csv') as ac, open('output/sws.txt', 'w') as sws:
reader = csv.reader(ac)
next(reader) # skip the header
for row in takewhile(lambda x: re.search(r'\A\s+', x[0]), reader):
print(row, file=sws)
这个对我来说很好,看起来很简单
import csv
import re
with open('C:\\results.csv', 'w') as sws:
with open('C:\\ascap.csv', 'r') as ac:
ascap = csv.reader(ac, delimiter=',')
for row in ascap:
if re.match('\s+', row[0]):
sws.write(str(row)+ '\n')
这并不能特别回答您的问题,但一般来说,使用
pandas
这样的库进行.csv处理会提高处理速度。也许您可以尝试先列出处理过的歌曲,然后在最后立即编写。不进行很多小的读写操作。@Jean-Françoisfare这是可能的,尽管我使用了append
来保留与每个歌曲发行者相关的值,这些值可能包含也可能不包含不同的数据值,例如角色类型、名称、共享等。
import csv
import re
from itertools import takewhile
with open('data/ascap_catalog1.csv') as ac, open('output/sws.txt', 'w') as sws:
reader = csv.reader(ac)
next(reader) # skip the header
for row in takewhile(lambda x: re.search(r'\A\s+', x[0]), reader):
print(row, file=sws)
import csv
import re
with open('C:\\results.csv', 'w') as sws:
with open('C:\\ascap.csv', 'r') as ac:
ascap = csv.reader(ac, delimiter=',')
for row in ascap:
if re.match('\s+', row[0]):
sws.write(str(row)+ '\n')