web-dev-qa-db-fra.com

Erreur de type pandas en essayant de tracer

J'essaie de créer un nuage de points de base basé sur un cadre de données Pandas. Mais lorsque j'appelle la routine scatter, l'erreur "TypeError: promotion de type non valide" est générée. Un exemple de code permettant de reproduire le problème est présenté ci-dessous:

t1 = pd.to_datetime('2015-11-01 00:00:00')
t2 = pd.to_datetime('2015-11-02 00:00:00')

Time = pd.Series([t1, t2])
r = pd.Series([-1, 1])

df = pd.DataFrame({'Time': Time, 'Value': r})
print(df)

print(type(df.Time))
print(type(df.Time[0]))

fig = plt.figure(figsize=(x_size,y_size))
ax = fig.add_subplot(111)
ax.scatter(df.Time, y=df.Value, marker='o')

La sortie qui en résulte est

        Time  Value
0 2015-11-01     -1
1 2015-11-02      1
<class 'pandas.core.series.Series'>
<class 'pandas.tslib.Timestamp'>

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-285-f4ed0443bf4d> in <module>()
     15 fig = plt.figure(figsize=(x_size,y_size))
     16 ax = fig.add_subplot(111)
---> 17 ax.scatter(df.Time, y=df.Value, marker='o')

C:\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in scatter(self, x,    y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, verts, **kwargs)
   3635             edgecolors = 'face'
   3636 
-> 3637         offsets = np.dstack((x, y))
   3638 
   3639         collection = mcoll.PathCollection(

C:\Anaconda3\lib\site-packages\numpy\lib\shape_base.py in dstack(tup)
    365 
    366     """
--> 367     return _nx.concatenate([atleast_3d(_m) for _m in tup], 2)
    368 
    369 def _replace_zero_by_x_arrays(sub_arys):

TypeError: invalid type promotion

En cherchant, j'ai trouvé un article similaire Pandas Series TypeError et ValueError avec datetime , ce qui suggère que l'erreur est due à la présence de plusieurs types de données dans la série. Mais cela ne semble pas être le problème dans mon exemple, comme en témoigne le type d'informations que j'imprime.

Notez que si j’arrête d’utiliser des objets datas de pandas et que je fais de la "Time" un nombre à la place, cela fonctionne très bien, par exemple.

t1 = 1.1 #
t2 = 1.2

Time = pd.Series([t1, t2])
r = pd.Series([-1, 1])

df = pd.DataFrame({'Time': Time, 'Value': r})
print(df)

print(type(df.Time))
print(type(df.Time[0]))

fig = plt.figure(figsize=(x_size,y_size))
ax = fig.add_subplot(111)
ax.scatter(df.Time, y=df.Value, marker='o')

avec sortie

   Time  Value
0   1.1     -1
1   1.2      1
<class 'pandas.core.series.Series'>
<class 'numpy.float64'>

et le graphique a l'air bien. Je ne sais pas pourquoi l'utilisation d'une date/heure est à l'origine de l'erreur de promotion de type non valide? J'utilise Python 3.4.3 et Pandas 0.16.2. 

16
Tom Johnson

Merci @martinvseticka. Je pense que votre évaluation est correcte sur la base du code numpy que vous m'avez indiqué. J'ai pu simplifier un peu plus vos réglages (et ajouté un troisième point d'échantillon) pour obtenir

t1 = pd.to_datetime('2015-11-01 00:00:00')
t2 = pd.to_datetime('2015-11-02 00:00:00')
t3 = pd.to_datetime('2015-11-03 00:00:00')

Time = pd.Series([t1, t2, t3])
r = pd.Series([-1, 1, 0.5])

df = pd.DataFrame({'Time': Time, 'Value': r})

fig = plt.figure(figsize=(x_size,y_size))
ax = fig.add_subplot(111)
ax.plot_date(x=df.Time, y=df.Value, marker='o')

La clé semble appeler "plot_date" plutôt que "plot". Cela semble informer mapplotlib de ne pas essayer de concaténer les tableaux.

9
Tom Johnson

Il y a une autre façon de supprimer les utilisations de la série. Il suffit d'utiliser la liste pour le temps. 

t1 = pd.to_datetime('2015-11-01 00:00:00')
t2 = pd.to_datetime('2015-11-02 00:00:00')

Time = pd.Series([t1, t2])
r = pd.Series([-1, 1])

df = pd.DataFrame({'Time': Time, 'Value': r})
print(df)

print(type(df.Time))
print(type(df.Time[0]))
x_size = 800
y_size = 600
fig = plt.figure(figsize=(x_size,y_size))
ax = fig.add_subplot(111)
ax.scatter(list(df.Time.values), list(df.Value.values), marker='o')
5
Jeff

Est-ce ce que vous recherchez?

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

t1 = pd.to_datetime('2015-11-01 00:00:00')
t2 = pd.to_datetime('2015-11-02 00:00:00')

idx = pd.Series([t1, t2])
s = pd.Series([-1, 1], index=idx)

fig, ax = plt.subplots()
ax.plot_date(idx, s, 'v-')
plt.tight_layout()
plt.show()

Je suis nouveau sur Python alors j'espère que je ne me trompe pas. Fondamentalement, j'ai essayé d'adapter votre exemple en fonction de https://stackoverflow.com/a/13674286/99256 .

Le problème avec votre script est que numpytente de concaténer les séries df.Time et df.Value et qu'il ne peut pas trouver un type approprié pour le nouveau tableau car un tableau est numérique et le second est composé d'instances Timestamp.

4
Martin Vseticka

Les graphes scatter ont des propriétés qui ne peuvent pas être simulées dans plot ou plot_date (en tant que possibilité de tracer des marqueurs avec des tailles variables).

La conversion de la série temporelle de type: pandas.tslib.Timestamp en une liste de type: datetime.datetime avant de tracer le diagramme de dispersion a fonctionné à mon avantage:

times = [d.to_pydatetime() for d in df.Time]]
ax.scatter(times, y=df.Value, marker='o')
3
N.C. van Gilse

Vous pouvez aussi faire quelque chose comme ça:

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

    df = pd.DataFrame({"Time":["2015-11-01 00:00:00", "2015-11-02 00:00:00"], "value":[ 1, -1]})
    df['Time'] = pd.to_datetime(df['Time'])
    fig, ax = plt.subplots()
    ax.scatter(np.arange(len(df['Time'])), df['value'], marker='o')
    ax.xaxis.set_ticks(np.arange(len(df['Time'])))
    ax.xaxis.set_ticklabels(df['Time'], rotation=90)
    plt.xlabel("Time")
    plt.ylabel("value")

    plt.show()
1
Gingerbread

J'ai changé le type de colonne datetime en chaîne dans fly:

plt.scatter(df['Date'].astype('str'), df['Category'], s=df['count'])

et le nuage de points fonctionne . Cordialement

1
Edward Weinert