【问题标题】:Labelling and Grouping Postcodes using Python使用 Python 标记和分组邮政编码
【发布时间】:2020-02-13 14:41:55
【问题描述】:

我对 Python 还很陌生,我正在尝试将各种邮政编码组合在预定义的标签下。例如“SA31”将被标记为“HywelDDAPostcode”

我有一些代码,我从一个单列文件中读取大量邮政编码到一个列表中,并将它们与预定义列表中的邮政编码进行比较。但是,当我输出我的邮政编码标签时,我的原始文件中的每个邮政编码只输出标签“UKPostcodes”。无论如何,我的代码中的前两个条件似乎总是评估为假。我使用“in”做正确的事吗?或者可能是文件读取问题?我不确定

输入文件只是一个包含邮政编码列表的文件(实际上它有数千行)

The CSV file

这是我的代码:

import csv

with open('postcodes.csv', newline='') as f:
    reader = csv.reader(f)
    your_list = list(reader)

my_list =[]
HywelDDAPostcodes=["SA46","SY23","SY24","SA18","SA16","SA43","SA31","SA65","SA61","SA62","SA17","SA48","SA40","SA19","SA20","SA44","SA15","SA14","SA73","SA32","SA67","SA45",
     "SA38","SA42","SA41","SA72","SA71","SA69","SA68","SA33","SA70","SY25","SA34","LL40","LL42","LL36","SY18","SY17","SY20","SY16","LD6"]

NationalPostcodes=["LL58","LL59","LL60","LL61","LL62","LL63","LL64","LL65","LL66","LL67","LL68","LL69","LL70","LL71","LL72","LL73","LL74","LL75","LL76","LL77","LL78",
                 "NP1","NP2","NP23","NP3","CF31","CF32","CF33","CF34","CF35","CF36","CF3","CF46","CF81","CF82","CF83","SA35","SA39","SA4","SA47","LL16","LL18","LL21","LL22","LL24","LL25","LL26","LL27","LL28","LL29","LL30","LL31","LL32","LL33","LL34","LL57","CH7","LL11","LL15","LL16","LL17","LL18","LL19","LL20","LL21","LL22","CH1","CH4","CH5","CH6","CH7","LL12","CF1","CF32","CF35","CF5","CF61","CF62","CF63","CF64","CF71","LL23","LL37","LL38","LL39","LL41","LL43","LL44","LL45","LL46","LL47","LL48","LL49","LL51","LL52","LL53","LL54","LL55","LL56","LL57","CF46","CF47","CF48","NP4","NP5","NP6","NP7","SA10","SA11","SA12","SA13","SA8","CF3","NP10","NP19","NP20","NP9","SA36","SA37","SA63","SA64","SA66","CF44","CF48","HR3","HR5","LD1","LD2","LD3","LD4","LD5","LD7","LD8","NP8","SY10","SY15","SY19","SY21","SY22","SY5","CF37","CF38","CF39","CF4","CF40","CF41","CF42","CF43","CF45","CF72","SA1","SA2","SA3","SA4","SA5","SA6","SA7","SA1","NP4","NP44","NP6","LL13","LL14","SY13","SY14"]


NationalPostcodes2= list(dict.fromkeys(NationalPostcodes))
labels=["HywelDDA","NationalPostcodes","UKPostcodes"]

for postcode in your_list:
    #print(postcode)
    if postcode in HywelDDAPostcodes:
        my_list.append(labels[0])
    if postcode in NationalPostcodes2:
        my_list.append(labels[1])
    else:
        my_list.append(labels[2])

with open('DiscretisedPostcodes.csv','w') as result_file:
    wr = csv.writer(result_file, dialect='excel')
    for item in my_list:
     wr.writerow([item,])

如果有人对可能导致问题的原因有任何建议,或者对 Python 有任何建议,总的来说,我将非常感激。谢谢!

【问题讨论】:

  • 您需要提供minimal reproducible example。主要问题是您没有提供输入文件,而且这些列表长得难以阅读,并且输出到文件似乎与问题无关。
  • 没有看到您的输入文件很难判断,但if postcode in ... 应该可以正常工作,我敢打赌文件的读取和解析会导致错误
  • 感谢您的回复,很抱歉没有包含该文件并且没有使帖子更具可读性。我现在已经包含了该文件,尽管除了将它们放在单独的文件中之外,我不确定如何使列表更具可读性。需要输出到文件,因为我需要以某种方式存储的邮政编码标签。

标签: python


【解决方案1】:

比较块不起作用的原因是,当您使用 csv 阅读器读取文件时,每一行都作为 list 添加到 your_list。所以你正在制作一个列表列表,当你比较那些不匹配的东西时。

['LL58'] == 'LL58'    # fails

所以,检查 your_list 并了解我的意思。您应该在读取文件之前创建一个 shell your_list,并在每个新读取文件时创建一个 append。然后检查它以确保它看起来不错。您还应该使用strip() 命令从每个项目中去除空格。我不记得 csv 阅读器是否会自动执行此操作。

另外...测试成员资格的更好结构是使用集合而不是列表。 in 适用于列表,但对于集合来说要快得多,所以我会将您的比较项目放入 sets

最后,不清楚你想用NationalPostcodes2 做什么。只需使用您的国家邮政编码,但将它们与{} 放在一起。

【讨论】:

  • 嗨 Jeff,非常感谢您的详细回复,这对我非常有帮助,我现在将使用 sets,这是我以前不知道的! NationalPostcodes2 最初是为了从 NationalPostcodes 中删除我最初错误输入的重复项
  • @Templar 您可能需要考虑的其他一些事情。你所拥有的很好,但你可以稍微调整你的设计。在阅读your_list 中的内容时,您可以“即时”执行操作。想想你会怎么做。然后,如果头脑没有被打乱,您也可以摆脱my_list 并“即时”编写您的输出。考虑一下这些设计模式......它不会对中小型设备产生任何明显的性能差异,但如果您必须摄取大量输入,它可以清理并加快速度。
【解决方案2】:

@Jeff H 的 answer 是正确的,但值得一提的是我可能会如何编写此代码(未经测试):

# Note: Since, as you wrote, these are only single-column files I did not use the csv
# module, as it will just add additional unnecessary overhead.

# Read the known data from files--this will always be more flexible and maintainable than
# hard-coding them in your code.  This is just one possible scheme for doing this; e.g.
# you could also put all of them into a single JSON file
standard_postcode_files = {
    'HywelDDA': 'hyweldda.csv',
    'NationalPostcodes': 'nationalpostcodes.csv',
    'UKPostcodes': 'ukpostcodes.csv'
}

def read_postcode_file(filename):
    with open(filename) as f:
        # exclude blank lines and strip additional whitespace
        return [line.strip() for line in f if line.strip()]

standard_postcodes = {}
for key, filename in standard_postcode_files.items():
    standard_postcodes[key] = set(read_postcode_file(filename))

# Assuming all post codes are unique to a set, map postcodes to the set they belong to
postcodes_reversed = {v: k for k, s in standard_postcodes.items() for v in s}

your_postcodes = read_postcode_file('postcodes.csv')

labels = [postcodes_reversed[code] for code in your_postcodes]

with open('DiscretisedPostCodes.csv', 'w') as f:
    for label in labels:
        f.write(label + '\n')

我可能会做其他事情,例如不将输入文件名硬编码。如果您需要使用 csv 模块处理多个列,只需进行最少的额外更改,但由于您每行只写一个项目,我认为这是不必要的。

【讨论】:

  • 谢谢Iguananaut,这很有见地!
猜你喜欢
  • 1970-01-01
  • 2011-04-11
  • 2013-04-05
  • 1970-01-01
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
相关资源
最近更新 更多