web-dev-qa-db-fra.com

Est-ce que Pandas) peut tracer un histogramme des dates?

J'ai pris ma série et je l'ai contrainte à une colonne datetime de dtype = datetime64[ns] (mais il ne faut que la résolution du jour ... je ne sais pas comment changer).

import pandas as pd
df = pd.read_csv('somefile.csv')
column = df['date']
column = pd.to_datetime(column, coerce=True)

mais le tracé ne fonctionne pas:

ipdb> column.plot(kind='hist')
*** TypeError: ufunc add cannot use operands with types dtype('<M8[ns]') and dtype('float64')

Je voudrais tracer un histogramme qui juste montre le nombre de dates par semaine, mois ou année.

Il y a sûrement un moyen de faire cela dans pandas?

73
lollercoaster

Étant donné ce df:

        date
0 2001-08-10
1 2002-08-31
2 2003-08-29
3 2006-06-21
4 2002-03-27
5 2003-07-14
6 2004-06-15
7 2003-08-14
8 2003-07-29

et si ce n'est pas déjà le cas:

df["date"] = df["date"].astype("datetime64")

Pour afficher le nombre de dates par mois:

df.groupby(df["date"].dt.month).count().plot(kind="bar")

.dt vous permet d'accéder aux propriétés datetime.

Ce qui vous donnera:

groupby date month

Vous pouvez remplacer mois par année, jour, etc.

Si vous voulez distinguer l'année et le mois par exemple, il suffit de faire:

df.groupby([df["date"].dt.year, df["date"].dt.month]).count().plot(kind="bar")

Qui donne:

groupby date month year

Était-ce ce que tu voulais? Est-ce clair?

J'espère que cela t'aides !

126
jrjc

Je pense que resample pourrait être ce que vous recherchez. Dans votre cas, faites-vous:

df.set_index('date', inplace=True)
# for '1M' for 1 month; '1W' for 1 week; check documentation on offset alias
df.resample('1M', how='count')

Il ne s'agit que de compter et non d'intrigue, vous devez donc créer vos propres parcelles.

Voir ce post pour plus de détails sur la documentation de resample documentation sur le rééchantillonnage des pandas

J'ai rencontré des problèmes similaires aux vôtres. J'espère que cela t'aides.

8
Ethan

Exemple rendu

enter image description here

Exemple de code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Create random datetime object."""

# core modules
from datetime import datetime
import random

# 3rd party modules
import pandas as pd
import matplotlib.pyplot as plt


def visualize(df, column_name='start_date', color='#494949', title=''):
    """
    Visualize a dataframe with a date column.

    Parameters
    ----------
    df : Pandas dataframe
    column_name : str
        Column to visualize
    color : str
    title : str
    """
    plt.figure(figsize=(20, 10))
    ax = (df[column_name].groupby(df[column_name].dt.hour)
                         .count()).plot(kind="bar", color=color)
    ax.set_facecolor('#eeeeee')
    ax.set_xlabel("hour of the day")
    ax.set_ylabel("count")
    ax.set_title(title)
    plt.show()


def create_random_datetime(from_date, to_date, Rand_type='uniform'):
    """
    Create random date within timeframe.

    Parameters
    ----------
    from_date : datetime object
    to_date : datetime object
    Rand_type : {'uniform'}

    Examples
    --------
    >>> random.seed(28041990)
    >>> create_random_datetime(datetime(1990, 4, 28), datetime(2000, 12, 31))
    datetime.datetime(1998, 12, 13, 23, 38, 0, 121628)
    >>> create_random_datetime(datetime(1990, 4, 28), datetime(2000, 12, 31))
    datetime.datetime(2000, 3, 19, 19, 24, 31, 193940)
    """
    delta = to_date - from_date
    if Rand_type == 'uniform':
        Rand = random.random()
    else:
        raise NotImplementedError('Unknown random mode \'{}\''
                                  .format(Rand_type))
    return from_date + Rand * delta


def create_df(n=1000):
    """Create a Pandas dataframe with datetime objects."""
    from_date = datetime(1990, 4, 28)
    to_date = datetime(2000, 12, 31)
    sales = [create_random_datetime(from_date, to_date) for _ in range(n)]
    df = pd.DataFrame({'start_date': sales})
    return df


if __== '__main__':
    import doctest
    doctest.testmod()
    df = create_df()
    visualize(df)
5
Martin Thoma

J'ai pu contourner ce problème en (1) traçant avec matplotlib au lieu d'utiliser directement le cadre de données et (2) en utilisant l'attribut values. Voir exemple:

import matplotlib.pyplot as plt

ax = plt.gca()
ax.hist(column.values)

Cela ne fonctionne pas si je n'utilise pas values, mais je ne sais pas pourquoi cela fonctionne.

2
abeboparebop

J'avais juste des problèmes avec ça aussi. J'imagine que puisque vous travaillez avec des dates, vous souhaitez conserver l'ordre chronologique (comme je l'ai fait).

La solution de contournement est alors

import matplotlib.pyplot as plt    
counts = df['date'].value_counts(sort=False)
plt.bar(counts.index,counts)
plt.show()

S'il vous plaît, si quelqu'un connaît une meilleure façon, s'il vous plaît parlez-en.

EDIT: pour jean ci-dessus, voici un échantillon des données [j'ai échantillonné de manière aléatoire à partir de l'ensemble de données complet, d'où les données triviales de l'histogramme.]

print dates
type(dates),type(dates[0])
dates.hist()
plt.show()

Sortie:

0    2001-07-10
1    2002-05-31
2    2003-08-29
3    2006-06-21
4    2002-03-27
5    2003-07-14
6    2004-06-15
7    2002-01-17
Name: Date, dtype: object
<class 'pandas.core.series.Series'> <type 'datetime.date'>

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-f39e334eece0> in <module>()
      2 print dates
      3 print type(dates),type(dates[0])
----> 4 dates.hist()
      5 plt.show()

/anaconda/lib/python2.7/site-packages/pandas/tools/plotting.pyc in hist_series(self, by, ax, grid, xlabelsize, xrot, ylabelsize, yrot, figsize, bins, **kwds)
   2570         values = self.dropna().values
   2571 
-> 2572         ax.hist(values, bins=bins, **kwds)
   2573         ax.grid(grid)
   2574         axes = np.array([ax])

/anaconda/lib/python2.7/site-packages/matplotlib/axes/_axes.pyc in hist(self, x, bins, range, normed, weights, cumulative, bottom, histtype, align, orientation, rwidth, log, color, label, stacked, **kwargs)
   5620             for xi in x:
   5621                 if len(xi) > 0:
-> 5622                     xmin = min(xmin, xi.min())
   5623                     xmax = max(xmax, xi.max())
   5624             bin_range = (xmin, xmax)

TypeError: can't compare datetime.date to float
1
EngineeredE

Je pense que pour résoudre ce problème, vous pouvez utiliser ce code, il convertit le type de date en types int:

df['date'] = df['date'].astype(int)
df['date'] = pd.to_datetime(df['date'], unit='s')

pour obtenir la date seulement, vous pouvez ajouter ce code:

pd.DatetimeIndex(df.date).normalize()
df['date'] = pd.DatetimeIndex(df.date).normalize()
1
user4329078