Metadata-Version: 2.4
Name: reg-normalizer
Version: 1.0.12
Summary: Tool for normalizing and standardizing Russian region names
Author-email: Vitovt Kopytok <vitovt.kopytok@gmail.com>
License: CC BY-NC-SA 4.0
Project-URL: Homepage, https://github.com/tochno-st/reg_normalizer
Project-URL: Documentation, https://github.com/tochno-st/reg_normalizer#readme
Project-URL: Repository, https://github.com/tochno-st/reg_normalizer
Project-URL: Bug Tracker, https://github.com/tochno-st/reg_normalizer/issues
Keywords: regions,normalization,russian,fuzzy-matching,data-cleaning
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: Free for non-commercial use
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Natural Language :: Russian
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: pyyaml>=6.0
Requires-Dist: fuzzywuzzy>=0.18.0
Requires-Dist: python-levenshtein>=0.20.0
Requires-Dist: pandas>=1.5.0
Requires-Dist: nltk>=3.8.0
Provides-Extra: dev
Requires-Dist: ipykernel; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"

[![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC_BY—NC—SA_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
[![PyPI version](https://badge.fury.io/py/reg-normalizer.svg)](https://badge.fury.io/py/reg-normalizer)
[![Python Versions](https://img.shields.io/pypi/pyversions/reg-normalizer.svg)](https://pypi.org/project/reg-normalizer/)


# Region Normalizer

**Region Normalizer** — инструмент для нормализации и стандартизации наименований российских регионов. Он помогает распознавать регион даже в случаях, когда в названии встречаются опечатки, латинские буквы или другие особенности написания. Инструмент сопоставляет различные формы написания с [эталонным справочником](https://github.com/tochno-st/reg_normalizer/blob/main/data/interim/regions_etalon_v2.0.yaml) и позволяет извлекать дополнительные атрибуты, такие как коды ОКАТО, ISO, английские названия и многое другое.

Разные наименования одного и того же региона — частая проблема в реальных данных, например, на портале ЕМИСС встречается до 275 различных вариантов написания регионов. Особенно многообразны варианты у Тюменской и Архангельской областей — по 8 и 7 вариантов соответственно. В состав этих регионов входят автономные округа (ХМАО, ЯНАО, НАО), и часть ведомств отмечает, что данные приведены без автономных округов, но сокращения и формулировки используются самые разные.

## Возможности
- Поиск и нормализация региона по произвольному названию (с учетом опечаток, сокращений, аббревиатур, смешения латиницы и кириллицы)
- Пакетная обработка больших таблиц с названиями регионов
- Гибкая настройка весов алгоритмов сопоставления
- Добавление дополнительных полей из эталонного справочника (ОКАТО, ISO, английское название и др.)

## Установка

Установите пакет с помощью pip:

```bash
pip install reg-normalizer
```

### Установка для разработки

Если вы хотите внести изменения в код:

1. Клонируйте репозиторий:

```bash
git clone https://github.com/tochno-st/reg_normalizer.git
cd reg_normalizer
```

2. Создайте виртуальное окружение с помощью `uv`:

```bash
uv venv
```

3. Активируйте виртуальное окружение:

**На macOS/Linux:**
```bash
source .venv/bin/activate
```

**На Windows:**
```bash
.venv\Scripts\activate
```

4. Установите зависимости для разработки:

```bash
uv pip install -e ".[dev]"
```

Или используйте традиционный подход с `pip`:

```bash
pip install -r requirements.txt
pip install -e ".[dev]"
```

## Разработка и тестирование

### Запуск тестов

Проект использует `pytest` для тестирования. Все тесты находятся в директории `tests/`.

**Запустить все тесты:**
```bash
pytest tests/ -v
```

**Запустить тесты с подробным выводом:**
```bash
pytest tests/ -v -s
```

**Запустить конкретный тестовый файл:**
```bash
pytest tests/test_indicators.py -v
pytest tests/test_regions_validator.py -v
```

**Запустить конкретный тест:**
```bash
pytest tests/test_indicators.py::test_get_indicator_descriptions -v
```

**Запустить тесты с покрытием кода:**
```bash
pytest tests/ --cov=reg_normalizer --cov-report=html
```

После выполнения команды отчет о покрытии будет доступен в `htmlcov/index.html`.

### Структура тестов

- `tests/test_indicators.py` — тесты для функций работы с индикаторами (`get_indicator_descriptions`, `attach_indicators`)
- `tests/test_regions_validator.py` — тесты для `RegionMatcher` и вспомогательных функций (`preprocess_name`, `stem_region_name`, `find_best_match`, `match_dataframe`, `attach_fields`)

### Работа с виртуальным окружением `uv`

Если вы используете `uv` для управления зависимостями:

**Создание нового окружения:**
```bash
uv venv
```

**Установка зависимостей:**
```bash
uv pip install -e ".[dev]"
```

**Обновление зависимостей:**
```bash
uv pip install --upgrade -e ".[dev]"
```

**Деактивация окружения:**
```bash
deactivate
```

## Быстрый старт

### 1. Импорт и инициализация

```python
from reg_normalizer import RegionMatcher

matcher = RegionMatcher()
```

### 2. Нормализация одного региона

```python
region_name = "московск область"
match, score = matcher.find_best_match(region_name)
print(f"Input: {region_name}")
print(f"Match: {match}")
print(f"Score: {score:.2f}")
```

### 3. Использование с DataFrame

```python
import pandas as pd
sample_data = pd.DataFrame({
    'region_name': [
        'московск Обл',
        'свердловск',
        'петербург',
        'Mосковская област',
        'татарстан респ.',
        'Свердлов обл',
        'aлтайский к',
        'Республика     Алтай',
        'ХМао',
        'Юж федеральный округ',
        'спб',
        'рт',
        'город москва столица российской федерации город федерального значения',
        'тюменская область (кроме ханты мансийского автономного округа югры и ямало ненецкого автономного округа)'
    ]
})

result_df = matcher.match_dataframe(
    sample_data,
    'region_name',
    weights={'levenshtein': 0.4, 'token_set': 0.6},
    approach_weights={'original': 0.3, 'stemmed': 0.7},
    threshold=70
)
```

### 4. Добавление дополнительных полей

```python
# Одно поле: передайте список из одного элемента
result_df = matcher.attach_fields(result_df, 'region_name', ['name_eng'])

# Несколько полей
result_df = matcher.attach_fields(result_df, 'region_name',
                                  ['name_eng', 'okato', 'iso_code'])

print(result_df.head())
```

## Кастомизация

- **weights** — веса для алгоритмов сравнения ('levenshtein', 'token_set')
- **approach_weights** — веса для подходов ('original', 'stemmed')
- **threshold** — пороговое значение для принятия совпадения

Пример:
```python
custom_weights = {'levenshtein': 0.3, 'token_set': 0.7}
custom_approach_weights = {'original': 0.2, 'stemmed': 0.8}
match, score = matcher.find_best_match(
    "свердловск",
    weights=custom_weights,
    approach_weights=custom_approach_weights,
    threshold=60
)
```

## Структура эталонного справочника

Файл [`data/interim/regions_etalon_v2.0.yaml`](https://github.com/tochno-st/reg_normalizer/blob/main/data/interim/regions_etalon_v2.0.yaml) содержит ключи:
- `name_rus` — официальное название региона
- `name_eng` — английское название
- `okato` — код ОКАТО
- `iso_code` — код ISO

## TODO

- [ ] Добавить обработку сокращений "Республика" (респ., р., Респ.)
- [ ] Расширить справочник замен аббревиатур и сокращений
- [ ] Решить проблему с фразами, в которых встречается "Российская Федерация", но это не регион
- [ ] Проверить, что хорошо обрабатываются вложенные автономные округа

## Лицензия

<a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br />
Creative Commons License Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).
