Как преобразовать столбец Pandas в тип даты, когда значения не соответствуют шаблону? - PullRequest
0 голосов
/ 20 марта 2020

У меня есть следующие данныеFrame:

    Timestamp           real time
0   17FEB20:23:59:50    0.003
1   17FEB20:23:59:55    0.003
2   17FEB20:23:59:57    0.012
3   17FEB20:23:59:57    02:54.8
4   17FEB20:24:00:00    0.03
5   18FEB20:00:00:00    0
6   18FEB20:00:00:02    54.211
7   18FEB20:00:00:02    0.051

Как преобразовать столбцы в datetime64?

Есть две вещи, которые делают эту сложную форму меня:

  1. Столбец Timestamp, индекс 4 имеет значение: 17FEB20:24:00:00, которое, по-видимому, не является действительной датой-временем (хотя оно было выведено программой SAS ...).
  2. Столбец real time не следует шаблону и, кажется, его нельзя сопоставить с помощью date_parser.

Это то, что я пытался обратиться к первому столбцу (Timestamp):

data['Timestamp'] = pd.to_datetime(
    data['Timestamp'],
    format='%d%b%y:%H:%M:%S')

Но из-за значения индекса 4 (17FEB20:24:00:00) я получаю: ValueError: time data '17FEB20:24:00:00' does not match format '%d%b%y:%H:%M:%S' (match). Если я удаляю эту строку, она работает, но мне нужно найти способ ее решения, так как в моем наборе данных тысячи строк, и я не могу их просто игнорировать. Возможно, есть способ преобразовать его в ноль часов следующего дня?

Вот фрагмент кода для создания образца dataFrame, как описано выше, чтобы получить некоторое время, работая над ответом (если вам нужно):

data = pd.DataFrame({
    'Timestamp':[
        '17FEB20:23:59:50',
        '17FEB20:23:59:55',
        '17FEB20:23:59:57',
        '17FEB20:23:59:57',
        '17FEB20:24:00:00',
        '18FEB20:00:00:00',
        '18FEB20:00:00:02',
        '18FEB20:00:00:02'],
    'real time': [
        '0.003',
        '0.003',
        '0.012',
        '02:54.8',
        '0.03',
        '0',
        '54.211',
        '0.051',
        ]})

Ценю вашу помощь!

Ответы [ 2 ]

1 голос
/ 21 марта 2020

Если ваши данные не слишком велики, вы можете рассмотреть возможность циклического перемещения по фрейму данных. Вы можете сделать что-то вроде этого.

for index, row in data.iterrows():
    if row['Timestamp'][8:10] == '24':
        date = (pd.to_datetime(row['Timestamp'][:7]).date() + pd.DateOffset(1)).strftime('%d%b%y').upper()
        data.loc[index, 'Timestamp'] = date + ':00:00:00'

Это результат.

        Timestamp      real time
0   17FEB20:23:59:50    0.003
1   17FEB20:23:59:55    0.003
2   17FEB20:23:59:57    0.012
3   17FEB20:23:59:57    02:54.8
4   18FEB20:00:00:00    0.03
5   18FEB20:00:00:00    0
6   18FEB20:00:00:02    54.211
7   18FEB20:00:00:02    0.051
0 голосов
/ 23 марта 2020

Вот как я к ней обратился:

  • Для столбца Timestamp я использовал этот ответ (Спасибо @ merit_2 за то, что поделились им в первом комментарии).
  • Для столбца real time я выполняю синтаксический анализ, используя некоторые условия.

Вот код:

import os
import pandas as pd
from datetime import timedelta

# Parsing "real time" column:

## Apply mask '.000' to the microseconds
data['real time'] = [sub if len(sub.split('.')) == 1 else sub.split('.')[0]+'.'+'{:<03s}'.format(sub.split('.')[1]) for sub in data['real time'].values]

## apply mask over all '00:00:00.000'
placeholders = {
    1: '00:00:00.00',
    2: '00:00:00.0',
    3: '00:00:00.',
    4: '00:00:00',
    5: '00:00:0',
    6: '00:00:',
    7: '00:00',
    8: '00:0',
    9: '00:',
    10:'00',
    11:'0'}

for cond_len in placeholders:
    condition = data['real time'].str.len() == cond_len
    data.loc[(condition),'real time'] = placeholders[cond_len] + data.loc[(condition),'real time']

# Parsing "Timestamp" column:
selrow = data['Timestamp'].str.contains('24:00')
data['Timestamp'] = data['Timestamp'].str.replace('24:00', '00:00')
data['Timestamp'] = pd.to_datetime(data['Timestamp'], format='%d%b%y:%H:%M:%S')
data['Timestamp'] = data['Timestamp'] + selrow * timedelta(days=1)

# Convert to columns to datetime type:
data['Timestamp'] = pd.to_datetime(data['Timestamp'], format='%d%b%y:%H:%M:%S')
data['real time'] = pd.to_datetime(data['real time'], format='%H:%M:%S.%f')

# check results:
display(data)
display(data.dtypes)

Вот вывод:

    Timestamp           real time
0   2020-02-17 23:59:50 1900-01-01 00:00:00.003
1   2020-02-17 23:59:55 1900-01-01 00:00:00.003
2   2020-02-17 23:59:57 1900-01-01 00:00:00.012
3   2020-02-17 23:59:57 1900-01-01 00:02:54.800
4   2020-02-18 00:00:00 1900-01-01 00:00:00.030
5   2020-02-18 00:00:00 1900-01-01 00:00:00.000
6   2020-02-18 00:00:02 1900-01-01 00:00:54.211
7   2020-02-18 00:00:02 1900-01-01 00:00:00.051

Timestamp    datetime64[ns]
real time    datetime64[ns]

Возможно, есть умный способ сделать это, но пока он подходит.

...