Другое

Как остановить преобразование строк Excel в научную нотацию

Узнайте, как в pandas избежать автоматического преобразования строк Excel вида '2004E205' в научную нотацию, используя параметр converters и другие методы.

Как предотвратить преобразование строк Excel с шаблонами вроде «2004E205» в научную нотацию в Pandas

Я работаю с файлами Excel в pandas и мне нужно обрабатывать строковые значения, содержащие шаблоны вроде «2004E205», которые являются уникальными кодами, используемыми в моей компании. Несмотря на явное указание типа столбца как строки с помощью параметра dtype, значения, содержащие шаблон xxxExxx, всё равно интерпретируются как научная нотация при чтении файла Excel. Например, «2004E205» преобразуется в «2004132141205».

Как я могу убедиться, что pandas читает эти значения как строки без автоматического преобразования при загрузке из файла Excel (не CSV)?

Я попробовал следующий подход:

python
import pandas as pd

# Assigning file path
2025_data = '/content/drive/MyDrive/Data Cleaning/2025-10 Data Checking/2025_data.xlsx'

# Reading all sheets
df_25_dict = pd.read_excel(2025_data, sheet_name=None),
    dtype={
        'bg_code': str,
        'tranx_date_year': str,
        'journal_number': str,
        'journal_line_number': str,
        'prj_code': str
    },
    parse_dates=['tranx_date', 'entry_date'])

# Iterate through the dictionary and print shape and columns for each sheet
for sheet_name, df in df_25_dict.items():
    print(f"Sheet: {sheet_name}")
    print(df.shape)
    print(df.columns)

Столбец, с которым у меня возникла проблема, — «bg_code». Какие дополнительные параметры или методы я могу использовать, чтобы предотвратить интерпретацию pandas этих строковых шаблонов как научной нотации?

Пандас автоматически преобразует строки, содержащие шаблоны вроде «2004E205», в научную нотацию при чтении файлов Excel, даже если явно указать dtype=str. Это происходит, потому что читатель Excel в Pandas имеет встроенную детекцию типов, которая может переопределить ваши явные указания dtype. Чтобы предотвратить это преобразование, необходимо использовать параметр converters вместо dtype, либо применять другие специфические методы, чтобы принудительно трактовать данные как строки.

Содержание

Понимание проблемы преобразования в научную нотацию

Проблема возникает из‑за того, что читатели Excel (как read_excel, так и внутренние движки) имеют автоматическую логику определения типов, которая интерпретирует строки, содержащие «E» или «e» с последующими цифрами, как научную нотацию. Это поведение проявляется даже при явном указании dtype=str для столбца.

Согласно документации Pandas по read_excel, параметр dtype задаёт тип данных для данных или столбцов, но он не всегда переопределяет автоматическое определение типов Excel, особенно для столбцов, которые выглядят как числовые шаблоны.

Преобразование происходит на этапе чтения Excel, до того как ваш параметр dtype полностью вступит в силу, поэтому «2004E205» становится «2004132141205» вместо того, чтобы оставаться исходной строкой.


Решение 1: Использование параметра Converters

Самый надёжный способ – использовать параметр converters вместо dtype. Параметр converters позволяет задать пользовательские функции преобразования, которые применяются до вывода типа данных.

python
import pandas as pd

df_25_dict = pd.read_excel(
    2025_data, 
    sheet_name=None,
    converters={
        'bg_code': str,  # Явно преобразовать в строку
        'tranx_date_year': str,
        'journal_number': str,
        'journal_line_number': str,
        'prj_code': str
    },
    parse_dates=['tranx_date', 'entry_date']
)

Параметр converters работает, применяя указанную функцию к каждому значению в столбце до того, как произойдёт вывод типа данных. Это гарантирует, что ваши значения будут преобразованы в строки до того, как Pandas попытается интерпретировать их как научную нотацию.

Как объяснено в документации Pandas по конвертерам, конвертеры применяются до параметра dtype, что делает их более эффективными для предотвращения нежелательных преобразований типов.


Решение 2: Использование движка OpenPyxl с конкретными настройками

Вы также можете указать движок и использовать дополнительные параметры для контроля поведения чтения:

python
df_25_dict = pd.read_excel(
    2025_data,
    sheet_name=None,
    engine='openpyxl',
    dtype={
        'bg_code': str,
        'tranx_date_year': str,
        'journal_number': str,
        'journal_line_number': str,
        'prj_code': str
    },
    parse_dates=['tranx_date', 'entry_date'],
    # Дополнительные параметры для предотвращения научной нотации
    na_values=[''],
    keep_default_na=False
)

Параметр engine='openpyxl' гарантирует, что вы используете современный движок Excel, который обеспечивает более точный контроль над поведением преобразования типов. Параметры na_values и keep_default_na помогают предотвратить интерпретацию пустых ячеек или специальных значений, которые могут вызвать преобразование в научную нотацию.

Согласно документации OpenPyxl, этот движок предоставляет более granular контроль над тем, как данные Excel читаются и интерпретируются по сравнению с движком по умолчанию.


Решение 3: Подход с постобработкой

Если вам нужно сохранить исходный параметр dtype, но при этом предотвратить преобразование в научную нотацию, вы можете выполнить постобработку данных после чтения:

python
# Сначала читаем без конвертеров, но с dtype
df_25_dict = pd.read_excel(
    2025_data,
    sheet_name=None,
    dtype={
        'bg_code': str,
        'tranx_date_year': str,
        'journal_number': str,
        'journal_line_number': str,
        'prj_code': str
    },
    parse_dates=['tranx_date', 'entry_date']
)

# Затем явно преобразуем любые столбцы, которые могли быть неверно интерпретированы
for sheet_name, df in df_25_dict.items():
    if 'bg_code' in df.columns:
        # Убедиться, что bg_code имеет тип строка
        df['bg_code'] = df['bg_code'].astype(str)

Этот подход сначала читает данные с вашими указанными dtypes, а затем явно преобразует любые столбцы, которые могли быть неверно интерпретированы. Метод astype(str) гарантирует, что все значения в столбце действительно являются строками.


Решение 4: Прямое использование ExcelReader

Для более продвинутого контроля вы можете использовать класс ExcelReader напрямую:

python
from pandas import ExcelFile

with ExcelFile(2025_data) as xls:
    df_25_dict = {}
    for sheet_name in xls.sheet_names:
        df = pd.read_excel(
            xls,
            sheet_name=sheet_name,
            dtype={
                'bg_code': str,
                'tranx_date_year': str,
                'journal_number': str,
                'journal_line_number': str,
                'prj_code': str
            },
            parse_dates=['tranx_date', 'entry_date'],
            converters={'bg_code': str}
        )
        df_25_dict[sheet_name] = df

Этот метод даёт вам больше контроля над процессом чтения и позволяет гарантировать, что конвертеры применяются последовательно во всех листах.


Лучшие практики и рекомендации

  1. Всегда используйте converters для критических строковых столбцов: Для столбцов, содержащих шаблоны, которые могут быть ошибочно интерпретированы, всегда используйте converters, а не полагайтесь только на dtype.
  2. Тестируйте с образцами данных: Перед обработкой больших файлов протестируйте ваш подход на небольшом примере, чтобы убедиться, что преобразование в научную нотацию предотвращено.
  3. Рассмотрите валидацию данных: После чтения реализуйте валидацию данных, чтобы убедиться, что ваши строковые столбцы содержат ожидаемый формат:
python
# Проверка формата bg_code (должен содержать 'E', но не быть научной нотацией)
def validate_bg_code(code):
    if not isinstance(code, str):
        return False
    # Должен содержать ровно один 'E' и цифры с обеих сторон
    return code.count('E') == 1 and code.replace('E', '').isdigit()

for sheet_name, df in df_25_dict.items():
    if 'bg_code' in df.columns:
        invalid_codes = df[~df['bg_code'].apply(validate_bg_code)]
        if not invalid_codes.empty:
            print(f"Warning: Invalid bg_code format in sheet {sheet_name}")
  1. Документируйте требования к данным: Ведите документацию о том, какие столбцы содержат специальные шаблоны, которые требуют особой обработки при чтении Excel.

Полный рабочий пример

Ниже приведён полный пример, демонстрирующий рекомендуемый подход:

python
import pandas as pd

def read_excel_with_string_preservation(file_path, string_columns, date_columns=None):
    """
    Чтение Excel-файла с сохранением строковых столбцов, которые могут быть ошибочно интерпретированы
    как научную нотацию.
    
    Параметры:
    - file_path: путь к Excel-файлу
    - string_columns: список названий столбцов, которые нужно сохранить как строки
    - date_columns: список названий столбцов, которые нужно распарсить как даты
    
    Возвращает:
    - Словарь DataFrame, один для каждого листа
    """
    if date_columns is None:
        date_columns = []
    
    # Используем конвертеры для гарантии сохранения строк
    converters = {col: str for col in string_columns}
    
    # Читаем Excel-файл
    df_dict = pd.read_excel(
        file_path,
        sheet_name=None,
        converters=converters,
        parse_dates=date_columns,
        engine='openpyxl',
        keep_default_na=False
    )
    
    # Дополнительная валидация
    for sheet_name, df in df_dict.items():
        for col in string_columns:
            if col in df.columns:
                # Убедиться, что все значения – строки
                df[col] = df[col].astype(str)
                
                # Проверка на наличие научной нотации
                scientific_pattern = df[col].str.contains(r'\d+E\d+', regex=True)
                if scientific_pattern.any():
                    print(f"Warning: Potential scientific notation found in {col} "
                          f"of sheet {sheet_name}")
    
    return df_dict

# Пример использования
file_path = '/content/drive/MyDrive/Data Cleaning/2025-10 Data Checking/2025_data.xlsx'
string_columns = ['bg_code', 'tranx_date_year', 'journal_number', 
                 'journal_line_number', 'prj_code']
date_columns = ['tranx_date', 'entry_date']

df_25_dict = read_excel_with_string_preservation(file_path, string_columns, date_columns)

# Вывод результатов
for sheet_name, df in df_25_dict.items():
    print(f"Sheet: {sheet_name}")
    print(f"Shape: {df.shape}")
    print(f"Columns: {list(df.columns)}")
    print(f"Sample bg_code values: {df['bg_code'].head().tolist()}")
    print("-" * 50)

Этот всесторонний подход гарантирует, что ваши строковые столбцы, содержащие шаблоны вроде «2004E205», сохранятся как строки без преобразования в научную нотацию, при этом оставаясь корректно обработанными датами и другими типами данных.

Источники

  1. Pandas read_excel Documentation
  2. Pandas User Guide - Excel Files
  3. OpenPyxl Documentation
  4. Pandas Data Type Conversion Guide

Вывод

Чтобы предотвратить преобразование Pandas строк Excel с шаблонами вроде «2004E205» в научную нотацию, следует:

  1. Использовать параметр converters вместо полагания только на dtype для столбцов с особыми шаблонами.
  2. Указать engine='openpyxl' для лучшего контроля над поведением чтения Excel.
  3. Внедрить пост‑обработку и валидацию, чтобы убедиться, что строковые столбцы сохраняют правильный формат.
  4. Тестировать на образцах данных перед обработкой больших файлов, чтобы убедиться в корректности подхода.

Параметр converters является самым надёжным решением, поскольку он применяет преобразование строк до любой типовой инференции, предотвращая интерпретацию ваших кодов как научной нотации. Комбинируя converters с правильным выбором движка и валидацией, вы можете гарантировать, что данные будут считаны точно так, как задумано, при сохранении всех остальных спецификаций типов данных.

Авторы
Проверено модерацией
Модерация