Сбой даты и времени при установке astype - PullRequest
0 голосов
/ 01 марта 2020

Я импортирую CSV из 20 переменных и 1500 записей. Существует 5 столбцов даты в формате даты в Великобритании: дд / мм / гггг, и импорт в формате .str. Мне нужно иметь возможность вычитать одну дату из другой. Это госпитальные поступления, - мне нужно вычесть дату выписки из даты поступления. чтобы получить продолжительность пребывания. У меня есть ряд проблем. Для иллюстрации я использовал 2 столбца.

import pandas as pd
import numpy as np
from datetime import datetime

import .csv

df = pd.read_csv("/Users........csv", usecols = ['ADMIDATE', 'DISDATE'])
df
    ADMIDATE    DISDATE
0   04/02/2018  07/02/2018
1   25/07/2017  1801-01-01
2   28/06/2017  01/07/2017
3   22/06/2017  1801-01-01
4   11/12/2017  15/12/2017
... ... ...
1503    25/01/2019  27/01/2019
1504    31/08/2018  1801-01-01
1505    20/09/2018  05/11/2018
1506    28/09/2018  1801-01-01
1507    21/02/2019  24/02/2019
1508 rows × 2 columns

Я удалил около 100 записей с DISDATE 1801-01-01, - это, вероятно, неверные данные о пациенте, все еще находящемся в больнице, когда данные были собраны. Чтобы преобразовать даты в datetime, я использовал .astype ('datetime64 [ns]'). Это потому, что я не знал, как использовать pd.to_datetime для нескольких столбцов.

df[['ADMIDATE', 'DISDATE']] = df[['ADMIDATE', 'DISDATE']].astype('datetime64[ns]')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1399 entries, 0 to 1398
Data columns (total 3 columns):
 #   Column      Non-Null Count  Dtype         
---  ------      --------------  -----         
 0   Unnamed: 0  1399 non-null   int64         
 1   ADMIDATE    1399 non-null   datetime64[ns]
 2   DISDATE     1391 non-null   datetime64[ns]
dtypes: datetime64[ns](2), int64(1)
memory usage: 32.9 KB

Итак, преобразование работает. Однако при проверке данных ADMIDATE стал yyyy-mm-dd, а DISDATE - yyyy-dd-mm.

df.head(20)
    Unnamed: 0  ADMIDATE    DISDATE
0   0   2018-04-02  2018-07-02
1   2   2017-06-28  2017-01-07
2   4   2017-11-12  2017-12-15
3   5   2017-09-04  2017-12-04
4   6   2017-05-30  2017-01-06
5   7   2017-02-08  2017-07-08
6   8   2017-11-17  2017-11-18
7   9   2018-03-14  2018-03-20
8   10  2017-04-26  2017-03-05
9   11  2017-05-16  2017-05-17
10  12  2018-01-17  2018-01-19
11  13  2017-12-18  2017-12-20
12  14  2017-02-10  2017-04-10
13  16  2017-03-30  2017-07-04
14  17  2017-01-12  2017-12-18
15  18  2017-12-07  2017-07-14
16  19  2017-05-04  2017-08-04
17  20  2017-10-30  2017-01-11
18  21  2017-06-19  2017-06-22
19  22  2017-04-05  2017-08-05

Поэтому, когда я вычитал ADMIDATE из DISDATE, я получал отрицательные значения.

df['DISDATE'] - df['ADMIDATE']
0        91 days
1      -172 days
2        33 days
3        91 days
4      -144 days
          ...   
1394    188 days
1395   -291 days
1396      2 days
1397   -132 days
1398      3 days
Length: 1399, dtype: timedelta64[ns]

Мне бы хотелось, чтобы метод работал со всеми моими столбцами даты, сохранял британский формат и позволял мне выполнять базовые c операции с полями даты.

После предложений @ code-Different, которые кажутся очень разумными ниже

for col in df.columns:
    df[col] = pd.to_datetime(df[col], dayfirst=True, errors='coerce')

Формат остается неизменным, несмотря на dayfirst = True.

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1399 entries, 0 to 1398
Data columns (total 3 columns):
 #   Column      Non-Null Count  Dtype         
---  ------      --------------  -----         
 0   Unnamed: 0  1399 non-null   datetime64[ns]
 1   ADMIDATE    1399 non-null   datetime64[ns]
 2   DISDATE     1391 non-null   datetime64[ns]
dtypes: datetime64[ns](3)
memory usage: 32.9 KB
df.head()

Unnamed: 0  ADMIDATE    DISDATE
0   1970-01-01 00:00:00.000000000   2018-04-02  2018-07-02
1   1970-01-01 00:00:00.000000002   2017-06-28  2017-01-07
2   1970-01-01 00:00:00.000000004   2017-11-12  2017-12-15
3   1970-01-01 00:00:00.000000005   2017-09-04  2017-12-04
4   1970-01-01 00:00:00.000000006   2017-05-30  2017-01-06

I также попробовал format='%d%m%Y' и все же год первый. Будет ли datetime.strptime хорошим?

Ответы [ 2 ]

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

просто скажите pandas.to_datetime, чтобы использовать указанный c и соответствующий формат, например:

import pandas as pd
import numpy as np

df = pd.DataFrame({'ADMIDATE': ['04/02/2018', '25/07/2017', 
                                '28/06/2017', '22/06/2017', '11/12/2017'],
                   'DISDATE': ['07/02/2018', '1801-01-01', 
                               '01/07/2017', '1801-01-01', '15/12/2017']}).replace({'1801-01-01': np.datetime64('NaT')})


for col in ['ADMIDATE', 'DISDATE']:
    df[col] = pd.to_datetime(df[col], format='%d/%m/%Y')

# df
#     ADMIDATE    DISDATE
# 0 2018-02-04 2018-02-07
# 1 2017-07-25        NaT
# 2 2017-06-28 2017-07-01
# 3 2017-06-22        NaT
# 4 2017-12-11 2017-12-15    

#   Column    Non-Null Count  Dtype         
# ---  ------    --------------  -----         
#  0   ADMIDATE  5 non-null      datetime64[ns]
#  1   DISDATE   3 non-null      datetime64[ns]
# dtypes: datetime64[ns](2)

Примечание: замените '1801-01-01' на np.datetime64('NaT'), чтобы вам не приходилось игнорировать ошибки, когда звонить pd.to_datetime.

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

to_datetime - это функция, которую вы хотите. Он не поддерживает несколько столбцов, поэтому вы просто l oop по столбцам один за другим. Строки в британском формате (день первый), поэтому вы просто говорите to_datetime, что:

df = pd.read_csv('/path/to/file.csv', usecols = ['ADMIDATE','DISDATE']).replace({'1801-01-01': pd.NA})

for col in df.columns:
    df[col] = pd.to_datetime(df[col], dayfirst=True, errors='coerce')

astype('datetime64[ns]') слишком негибко для того, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...