Сопоставление тысяч данных занимает слишком много времени при использовании Pandas
Каждый день я получаю отчет с некоторыми значениями, и мне нужно сопоставить почтовые индексы стран по всему миру, чтобы получить правильный регион. Затем я загружаю результат в мое приложение Django. Вот взгляд на мой отчет:
Order Number | Date | City | Postal code |
---|---|---|---|
930276 | 27/09/2022 | Madrid | cp: 28033 |
929670 | 27/09/2022 | Lisboa | cp: 1600-812 |
У меня есть тысячи таких строк. Задача состоит в том, чтобы получить регион в формате ISO 3166-2. Чтобы помочь себе, я обратился к следующей странице Geonames и загрузил информацию обо всех странах (пример: "FR.txt", "ES.txt"...).
Поскольку это огромный txt
файл, я решил хранить его на сервере S3.
Вот что я попробовал:
def access_scaleway(region_name, endpoint_url, access_key, secret_key):
""" Accessing Scaleway Bucket """
scaleway = boto3.client('s3', region_name=region_name, endpoint_url=endpoint_url, aws_access_key_id=access_key,
aws_secret_access_key=secret_key)
return scaleway
def get_region_code_accessing_scaleway(countries, regions):
''' Retrieves the region code from the region name. '''
list_countries = countries
list_regions = regions
list_regions_codes = []
scaleway_session = access_scaleway(region_name=settings.SCALEWAY_S3_REGION_NAME,
endpoint_url=settings.SCALEWAY_S3_ENDPOINT_URL,
access_key=settings.SCALEWAY_ACCESS_KEY_ID,
secret_key=settings.SCALEWAY_SECRET_ACCESS_KEY)
for country, region in zip(list_countries, list_regions):
try:
obj = scaleway_session.get_object(Bucket=settings.SCALEWAY_STORAGE_BUCKET_NAME, Key=f'countries/{country}.txt')
df = pd.read_csv(io.BytesIO(obj['Body'].read()), sep='\t', header=None)
df.columns = ['country code', 'postal code', 'place name', 'admin name1', 'admin code1', 'admin name2', 'admin code2', 'admin name3', 'admin code3', 'latitude', 'longitude', 'accuracy']
df['postal code'] = df['postal code'].astype(str)
df['postal code'] = df['postal code'].str.zfill(5)
# Removing all spaces and special characters
postal_code = re.sub("[^0-9^-]", '', region).strip()
region_code = country + "-" + df[df['postal code'] == postal_code]['admin code1'].values[0]
list_regions_codes.append(region_code)
except AttributeError:
list_regions_codes.append(None)
except ValueError:
list_regions_codes.append(None)
return list_regions_codes
Но это слишком долго. Для простого отчета из 1000 строк требуется около 30 минут.
Моя вторая попытка заключалась в использовании публичного API OpenDataSoft
. Вот что я попробовал:
def fetch_data(url, params, headers=None):
response = requests.get(url=url, params=params, headers=headers)
return response
def get_region_code_accessing_scaleway(countries, regions):
''' Retrieves the region code from the region name. '''
list_countries = countries
list_regions = regions
list_regions_codes = []
for country, region in zip(list_countries, list_regions):
try:
#Get response from API
postal_code = re.sub("[^0-9^-]", '', region).strip()
response = fetch_data(
url="https://data.opendatasoft.com/api/v2/catalog/datasets/geonames-postal-code%40public/records?",
params="select=country_code%2C%20postal_code%2C%20admin_code1&where=country_code%3D%22" + country + "%22%20and%20postal_code%3D%22" + postal_code + "%22")
if response.status_code == 200:
data = response.json()
if len(data['records']) > 0:
list_regions_codes.append(country + "-" + data['records'][0]['record']['fields']['admin_code1'])
else:
list_regions_codes.append(None)
else:
print('Error:" + response.status_code')
list_regions_codes.append(None)
Но опять же, для получения совпадающих значений требуется вечность.
Последнее, что я попробовал, это pgeocode
, но это тоже слишком долго.
Я не понимаю, почему он такой длинный, ведь желаемый результат - вот этот:
Order Number | Date | City | Postal code | Region code |
---|---|---|---|---|
930276 | 27/09/2022 | Madrid | cp: 28033 | ES-MD |
929670 | 27/09/2022 | Lisboa | cp: 1600-812 | PT-08 |
Есть ли у вас идеи, как ускорить процесс?