Estoy tratando de crear una especie de "funcional de selección" que ofrece a los usuarios la flexibilidad para crear la configuración para seleccionar los datos en tramas de datos pandas. Sin embargo, me encontré con algunos problemas que me rompecabezas.
El siguiente es un ejemplo simplificado:
>>> import pandas as pd
>>> df = pd.DataFrame({'date': pd.date_range(start='2020-01-01', periods=4), 'val': [1, 2, 3, 4]})
>>> df
date val
0 2020-01-01 1
1 2020-01-02 2
2 2020-01-03 3
3 2020-01-04 4
Pregunta 1: ¿Por qué recibo resultado diferente cuando aplico la función de la columna de forma diferente?
>>> import datetime
>>> bydatetime = lambda x : x == datetime.date(2020, 1, 1)
>>> bydatetime(df['date'])
0 False
1 False
2 False
3 False
Name: date, dtype: bool
>>> df['date'].apply(bydatetime) # why does this one work?
0 True
1 False
2 False
3 False
Name: date, dtype: bool
Sin embargo si uso de numpy datetime64
o pandas Timestamp
tipos para crear la función lambda, que funcionaría.
>>> import numpy as np
>>> bynpdatetime = lambda x : x == np.datetime64('2020-01-01')
>>> bynpdatetime(df['date'])
0 True
1 False
2 False
3 False
Name: date, dtype: bool
>>> df['date'].apply(bynpdatetime)
0 True
1 False
2 False
3 False
Name: date, dtype: bool
>>> bypdtimestamp = lambda x : x == pd.Timestamp('2020-01-01')
>>> bypdtimestamp(df['date'])
0 True
1 False
2 False
3 False
Name: date, dtype: bool
>>> df['date'].apply(bypdtimestamp)
0 True
1 False
2 False
3 False
Name: date, dtype: bool
Así que volvió a utilizar la siguiente selección simple, y usando datetime.date
no funcionaba. Si datetime.date
simplemente no funcionaría, ¿por qué df['date'].apply(bydatetime)
trabajar?
>>> df[df['date'] == datetime.date(2020, 1, 1)]
Empty DataFrame
Columns: [date, val]
Index: []
>>> df[df['date'] == np.datetime64('2020-01-01')]
date val
0 2020-01-01 1
>>> df[df['date'] == pd.Timestamp('2020-01-01')]
date val
0 2020-01-01 1
Por último, pero no menos importante, ¿por qué es el tipo de la date
columna datetime64
en la trama de datos, pero Timestamp
cuando se selecciona una celda? ¿Cuál es exactamente la diferencia entre ellos?
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 4 non-null datetime64[ns]
1 val 4 non-null int64
dtypes: datetime64[ns](1), int64(1)
memory usage: 192.0 bytes
>>>
>>> df['date'][0]
Timestamp('2020-01-01 00:00:00')
Estoy seguro de que hay algo fundamental que no entiendo aquí. Muchas gracias por nada constructivo.
Por suerte tengo una versión anterior de pandas
(0.25) y se obtiene una advertencia cuando lo hace bynpdatetime(df['date'])
, lo que explica exactamente por qué se ve que el comportamiento. Hubo un poco de un lado a otro sobre la manera de manejar esto así que ver este comportamiento será la versión altamente específico:
FutureWarning: Comparación de la serie de datetimes con 'datetime.date'. Actualmente, el 'datetime.date' es forzado a una fecha y hora. En el futuro, los pandas no coaccionará, y 'los valores no se compara igual a la 'datetime.date'. Para mantener el comportamiento actual, convertir el 'datetime.date' a una fecha y hora con 'pd.Timestamp'.
Fecha y hora en la funcionalidadpandas
se basa en la np.datetime64
y np.timedelta64
dtypes. No debe utilizar el módulo de fecha y hora , ya que han hecho ciertas decisiones que sean incompatibles con la biblioteca estándar. Todo el comportamiento no deseado es debido a esto.
Para responder a la otra cuestión relacionada con la ONU. datetime64
es como el de tipo de matriz o el concepto. Esa matriz (en este caso una pd.Series
) se compone de escalar timedelta64
objetos. Esto se explica en la documentación