Парсинг данных в pandas, python - PullRequest
2 голосов
/ 20 июня 2020

У меня есть файл Excel со многими столбцами, один из них, «Столбец3» - это дата с некоторым текстом в нем, в основном это выглядит так:

26/05/20
XXX
YYY
12/05/2020

Данные записываются в DD / MM Формат / YY, но pandas, как и в excel, считает, что 05.12.2020 это 05 декабря c 2020, а это 12 мая 2020 года. (Мой windows установлен в американский формат даты)

Важное примечание: когда я открываю стандартный файл excel, ячейки с 12/05/2020 уже имеют тип даты, пытаясь преобразовать его в текст, он дает мне 44170, который даст мне неправильную дату, если я просто переформатирую его в DD / MM / YY

Я добавил эту строку кода:

iport pandas as pd
    
dateparse = lambda x: pd.datetime.strptime(x,'%d/%m/%y')
df = pd.read_excel("my_file.xlsx", parse_dates=['Column3'], date_parser=dateparse)

Но текст в столбце генерирует ошибку.

ValueError: time data 'XXX' does not match format '%d/%m/%y'

Я пошел дальше и вручную удалил все текст (очевидно, я не могу делать это все время), чтобы узнать, работает ли он или нет, но затем я получил следующую ошибку

dateparse = lambda x: pd.datetime.strptime(x,'%d/%m/%y')
TypeError: strptime() argument 1 must be str, not datetime.datetime

Я также пробовал это:

df['Column3'] = pd.to_datetime(df.Column3, format ='%d/%m/%y', errors="coerce") 
# if I make errors="ignore" it doesn't change anything.

в этом случае мой 26/05/20 был правильно преобразован в 26 мая 2020 года, но я потерял все свои текстовые данные (это нормально) и другие даты, которые ch не соответствует моему аргументу формата. Потому что раньше они считались датами американского типа.

Моя цель - преобразовать данные в столбце 3 в тот же формат, чтобы я мог применять фильтры с pandas. Я думаю, что это пара решений:

  1. сказать Pandas, чтобы вообще не преобразовывать текст в дату (но он уже сохранен как тип даты в стандартном файле, это будет работать?)
  2. как-то игнорировать текстовые значения и использовать метод date_parser = co convert добавить даты в DD / MM / YY
  3. с помощью pd.to_datetime convert 26/05/20 to 26 May 2020, а затем конвертировать 2020-09-06 С 00:00:00 до 9 июня 2020 г. (кажется, самый простой, но аргумент игнорировать не работает.)

Вот ссылка на небольшой образец файла https://easyupload.io/ca5p6w

Ответы [ 3 ]

1 голос
/ 20 июня 2020

Вы можете передать date_parser в read_excel:

dateparser = lambda x: pd.to_datetime(x, dayfirst=True)

pd.read_excel('test.xlsx', date_parser = dateparser)
1 голос
/ 21 июня 2020

Публикуем это как ответ, так как он слишком длинный для комментария

Проблема возникла в Excel. Если я открываю его в Excel, я вижу 2 строки, которые выглядят как даты 26/05/20, 05/12/2020 и 06/02/2020. Обратите внимание на разницу между 20 и 2020 В строках 24 и 48 я вижу даты в столбце 4. Кажется, это указывает на то, что Excel собран. Этот Excel собран копипастом или программно?

загрузка его только pd.read_excel дает следующие результаты для дат:

  • 26/05/20
  • 2020-12-05 00: 00: 00
  • 2020-02-06 00: 00: 00

Если я это сделаю df["Column3"].apply(type) даст мне

  • стр

Итак, в файле Excel они отмечены как datetime.

Загрузка их с помощью df = pd.read_excel(DATA_DIR / "sample.xlsx", dtype={"Column3": str}) изменяет тип всех на str, но не меняет вывод.

Если вы откроете извлечение файла и go посмотрите непосредственно на xml файл xl\worksheets\sheet1.xml и найдите ячейку C26, вы увидите ее как 44170, а C5 - 6, что это ссылка на 26/05/20 в xl/sharedStrings.xml

Как «сделать» этот файл Excel? Лучше всего решить эту проблему, составив этот файл.

Обходной путь

Как обходной путь, вы можете преобразовать даты по частям. Другой формат позволяет это:

format1 = "%d/%m/%y"
format2 = "%Y-%d-%m %H:%M:%S"

Затем вы можете сделать pd.to_datetime(dates, format=format1, errors="coerce"), чтобы получить только первые даты, и NaT для тех, которые не соответствуют формату. Затем вы используете combine_first для заполнения пустот.

dates = df["Column3"]  # of the one imported with dtype={"Column3": str}
dates_parsed = (
    pd.to_datetime(dates, format=format1, errors="coerce")
    .combine_first(pd.to_datetime(dates, format=format2, errors="coerce"))
    .astype(object)
    .combine_first(dates)
)

astype(object) необходим для заполнения пустых мест строковыми значениями.

0 голосов
/ 20 июня 2020

Я думаю, сначала вы должны импортировать файл без разбора даты, а затем преобразовать его в формат даты, используя следующее:

df ['column3'] = pd.to_datetime (df ['column3'], errors = 'coerce')

Надеюсь, это сработает

...