我正在尝试将regex .findall()搜索的结果保存到csv中,但是很难将结果附加到输出文件中。
由于我对Python还是很陌生,所以我试图将这个问题限制为仅使用csv和re库-但是,如果有一种更简单的方法(例如,在熊猫中),这也将有所帮助。
如何将输入CSV的全部内容复制到输出CSV并将邮政编码/找到的正则表达式添加到找到它的行?
我是否有任何明显形式的错误检查或其他遗漏的东西?
是否存在一种更好的方法,可以将输入CSV的标头自动添加到输出CSV而无需显式指定它们?
是否可以使用DictWriter做到这一点?正如我最初尝试的那样。
import csv, re
pattern = r'[A-Z]{1,2}[0-9R][0-9A-Z]?[0-9][A-Z]{2}'
postcodes = []
with open(r'Postcode/addressin.csv', 'r') as csvinput:
csv_reader = csv.DictReader(csvinput)
with open(r'Postcode/addressout.csv', 'w', newline='') as csvoutput:
fieldnames = ['Address', 'Name']
csv_writer = csv.writer(csvoutput)
csv_writer.writerow(fieldnames)
for line in csv_reader:
postcodes = re.findall(pattern, line["Address"])
csv_writer.writerow(postcodes)
示例数据:
Address,Name,Lat,Long,2016 Sales,Type
48 Park Avenue, LATTON, SN6 4SZ,Nikki Yellowbeard,-23.17549,36.74641,9727,AA
IV21 1TD 116 Walwyn Rd CHARLESTOWN,Jonh Doe,-10.98309,156.41854,11932,AE
答案 0 :(得分:0)
最好将输入的csv文件读入数据框中,然后使用pandas.str.extract()从地址栏中提取邮政编码。
答案 1 :(得分:0)
在我看来,第一个字段地址中会出现逗号,这会造成不规则现象,但我不确定是哪种方法绕过那些错误的最佳方法,但这种表达方式是这样的:
(.*),(.*),\s*([0-9.-]+)\s*,\s*([0-9.]+)\s*,([0-9]{4,5}(?:-[0-9]{4})?)\s*,\s*([A-Z]{2})
可能是一种研究方法。
美国邮政编码通常采用以下格式:
([0-9]{5}(?:-[0-9]{4})?)
仅出于演示目的,我包括:
[0-9]{4,5}
您可以将其删除。
import re
regex = r"(.*),(.*),\s*([0-9.-]+)\s*,\s*([0-9.]+)\s*,([0-9]{4,5}(?:-[0-9]{4})?)\s*,\s*([A-Z]{2})"
test_str = ("Address,Name,Lat,Long,2016 Sales,Type\n"
"48 Park Avenue, LATTON, SN6 4SZ,Nikki Yellowbeard,-23.17549,36.74641,9727,AA\n"
"IV21 1TD 116 Walwyn Rd CHARLESTOWN,Jonh Doe,-10.98309,156.41854,11932,AE")
matches = re.finditer(regex, test_str, re.MULTILINE)
for matchNum, match in enumerate(matches, start=1):
print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))
for groupNum in range(0, len(match.groups())):
groupNum = groupNum + 1
print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))
如果我们不验证值,则只需使用此表达式
(.*),(.*),(.*),(.*),(.*),(.*)
可能可行。
答案 2 :(得分:0)
您的样本中的CSV无效;看来您缺少在“地址”字段周围的引号。
此外,re.findall()
可以返回多个结果-CSV不能真正在一个列中容纳多个值(而且当您尝试陷入混乱之中时,您现在想摆脱的困境) );通常,更好的解决方案是对数据进行规范化,以使每个字段都包含一个最小的原子数据,这些数据无法进一步分为较小的信息单元。
如果您要表示嵌套或分层数据,则可以使用JSON或XML而不是CSV作为存储格式。
通过这种方式,这是一个重构,它在每行的末尾添加一个字段,并在其中嵌入用分号分隔的邮政编码列表(如果正则表达式匹配不成功,则不添加任何代码)字段。
import csv, re
# Precompile the pattern
pattern = reccompile(r'[A-Z]{1,2}[0-9R][0-9A-Z]?[0-9][A-Z]{2}')
with open(r'Postcode/addressin.csv', 'r') as csvinput, open(r'Postcode/addressout.csv', 'w') as csvoutput:
csv_reader = csv.DictReader(csvinput)
csv_writer = csv.writer(csvoutput)
outputfieldnames = ['Address', 'Name', 'Postcode']
csv_writer.writerow(outputfieldnames)
for line in csv_reader:
postcodes = ';'.join(pattern.findall(line["Address"]))
csv_writer.writerow([line["Address"], line["Name"], postcodes])