Pandalar tarihlerin histogramını çizebilir mi?


106

Serimi aldım ve dtype = datetime sütununa zorladım datetime64[ns](sadece gün çözünürlüğüne ihtiyacım var ... nasıl değiştirileceğinden emin değilim).

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

ama komplo çalışmıyor:

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

Sadece tarihlerin sayısını haftaya, aya veya yıla göre gösteren bir histogram çizmek istiyorum .

Elbette bunu yapmanın bir yolu var pandasmı?


2
Elinizdeki df'nin bir örneğini gösterebilir misiniz?
jrjc

Yanıtlar:


172

Bu df göz önüne alındığında:

        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

ve zaten durum böyle değilse:

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

Aylara göre tarih sayısını göstermek için:

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

.dt datetime özelliklerine erişmenizi sağlar.

Hangisi size verecek:

aya göre grup

Ayı yıl, gün vb. İle değiştirebilirsiniz.

Örneğin yılı ve ayı birbirinden ayırmak istiyorsanız, şunu yapın:

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

Hangi verir:

grup tarihine göre ay yıl

İstediğin bu muydu? Bu anlaşıldı mı?

Bu yardımcı olur umarım !


1
Birkaç yıla yayılan verileriniz varsa, tüm 'ocak' verileri her ay aynı sütuna vb. Yerleştirilir.
drevicko

Çalışıyor, ancak benim için (pandalar 0.15.2) tarihler büyük harfle yazılmalıdır D: df.groupby (df.Date.dt.month) .count (). Plot (kind = "bar")
harbun

@drevicko: İnanıyorum bekleniyor. @harbun: dateveya Dateburada sütun adları var, bu nedenle tarih içeren sütununuzun adı foo ise şöyle olacaktır:df.foo.dt.month
jrjc

@jeanrjc Soruya tekrar baktığımda sanırım haklısın. Yıllara göre ayırt etmesi gereken benim gibi diğerleri için groupby, bir sütun verisinin iki niteliğinin kombinasyonunu bulmanın basit bir yolu var mı (örneğin: yıl ve tarih)?
drevicko

Tarihleri, tarihlerin histogramını çizmek için seaborn.distplot () kullanabilmem için hazırlamanın bir yolu var mı?
panc

11

Bence aradığınız şey yeniden örnekleme olabilir. Sizin durumunuzda şunları yapın:

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')

Sadece saymayı yapıyor, arsa değil, bu yüzden kendi planlarınızı yapmanız gerekiyor.

Yeniden örnekleme pandaları yeniden örnekleme belgelerinin dokümantasyonu hakkında daha fazla ayrıntı için bu gönderiye bakın

Senin yaptığın gibi benzer sorunlarla karşılaştım. Bu yardımcı olur umarım.


2
howkullanımdan kaldırıldı. Yeni sözdizimidf.resample('1M').count()
Dan Weaver

7

Oluşturulan örnek

görüntü açıklamasını buraya girin

Örnek Kod

#!/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 __name__ == '__main__':
    import doctest
    doctest.testmod()
    df = create_df()
    visualize(df)

5

(1) Dataframe'i doğrudan kullanmak yerine matplotlib ile çizim yaparak ve (2) valuesözniteliği kullanarak bu sorunu çözmeyi başardım . Örneğe bakın:

import matplotlib.pyplot as plt

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

Kullanmazsam bu işe yaramaz values, ama neden işe yaradığını bilmiyorum.


3

İşte beklediğiniz gibi bir histograma sahip olmak istediğiniz zamanlar için bir çözüm. Bu groupby kullanmaz, ancak tarih saat değerlerini tam sayılara dönüştürür ve grafikteki etiketleri değiştirir. Onay etiketlerini eşit yerlere taşımak için bazı iyileştirmeler yapılabilir. Ayrıca yaklaşımla bir çekirdek yoğunluğu tahmin grafiği (ve herhangi bir başka grafik) da mümkündür.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.DataFrame({"datetime": pd.to_datetime(np.random.randint(1582800000000000000, 1583500000000000000, 100, dtype=np.int64))})
fig, ax = plt.subplots()
df["datetime"].astype(np.int64).plot.hist(ax=ax)
labels = ax.get_xticks().tolist()
labels = pd.to_datetime(labels)
ax.set_xticklabels(labels, rotation=90)
plt.show()

Tarih saat histogramı


1

Sanırım bu sorunu çözmek için bu kodu kullanabilirsiniz, tarih türünü int türlerine dönüştürür:

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

sadece tarih almak için bu kodu ekleyebilirsiniz:

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

1
bu, sıralı bir tarih-saat histogramının nasıl çizileceği sorusuna yanıt vermiyor mu?
lollercoaster

Sanırım datetime tipindeki probleminiz,


1

Ben de bununla sorun yaşıyordum. Tarihlerle çalıştığınız için kronolojik sıralamayı korumak istediğinizi hayal ediyorum (benim yaptığım gibi).

Çözüm daha sonra

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

Lütfen, daha iyi bir yol bilen varsa lütfen konuşun.

DÜZENLEME: yukarıdaki jean için, işte verilerin bir örneği [Tam veri kümesinden rastgele örnekledim, dolayısıyla önemsiz histogram verileri.]

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

Çıktı:

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

Tüm bu cevaplar aşırı derecede karmaşık görünüyor, en azından 'modern' pandalarda iki satır.

df.set_index('date', inplace=True)
df.resample('M').size().plot.bar()

1
Bu, yalnızca bir a sahipseniz işe yarıyor gibi görünüyor DataFrame, ancak sahip olduğunuz tek şey bir Series. Bu vakaya bir not eklemeyi düşünür müsün?
David Z
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.