2

I am trying to plot an x-y plot, with x or y as date variable, and using a 3rd variable to color the points. I managed to do it if none of the 3 variables are date, using:

ax.scatter(df['x'],df['y'],s=20,c=df['z'], marker = 'o', cmap = cm.jet )

After searching, I find out that for normal plot, we have to use plot_date(). Unfortunately, I haven't been able to color the points. Can anybody help me?

Here is a small example:

import matplotlib, datetime
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import pandas as pd

todayTime=datetime.datetime.now();
df = pd.DataFrame({'x': [todayTime+datetime.timedelta(hours=i) for i in range(10)], 'y': range(10),'z' : [2*j for j in range(10)]});
xAlt=[0.5*i for i in range(10)];

fig, ax = plt.subplots()
ax.scatter(df['x'],df['y'],s=20,c=df['z'], marker = 'o', cmap = cm.jet )
plt.show()

You can replace df['x'] by xAlt to see the desired result

Thank you

Kil.Th
  • 75
  • 6

1 Answers1

2

As far as I know, one has to use scatter in order to color the points as you describe. One workaround could be to use a FuncFormatter to convert the tick labels into times on the x-axis. The code below converts the dates into numbers, makes the scatter plot, and uses a FuncFormatter to convert the tick labels back into dates.

import matplotlib, datetime
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import pandas as pd
from matplotlib.ticker import FuncFormatter

todayTime=datetime.datetime.now()
df = pd.DataFrame({'x': [todayTime+datetime.timedelta(hours=i) for i in  range(10)], 'y': range(10),'z' : [2*j for j in range(10)]})

def my_formatter(x, pos=None):
    d = matplotlib.dates.num2date(x)
    if len(str(d.minute)) == 1:
        mn = '0{}'.format(d.minute)
    else:
        mn = str(d.minute)
    if len(str(d.hour)) == 1:
        hr = '0{}'.format(d.hour)
    else:
        hr = str(d.hour)
    return hr+':'+mn

major_formatter=FuncFormatter(my_formatter)

nums = np.array([matplotlib.dates.date2num(di) for di in df['x']])

fig, ax = plt.subplots()
ax.xaxis.set_major_formatter(major_formatter)
ax.scatter(nums,df['y'],s=20,c=df['z'], marker = 'o', cmap = cm.jet )
xmin = df['x'][0]-datetime.timedelta(hours=1)
xmax = df['x'][len(df['x'])-1]+datetime.timedelta(hours=1)
ax.set_xlim((xmin,xmax))
plt.show()
Angus Williams
  • 2,284
  • 19
  • 21
  • Thank you for your answer. Unfortunately, this is not what I am expecting. It already works for xAlt. I would like to do: ax.scatter(df['x'],df['y'],s=20,c=df['z'], marker = 'o', cmap = cm.jet ) – Kil.Th Sep 21 '16 at 10:44
  • The point is to plot using `xAlt`, but then to convert `xAlt` -> `df['x']` in the x-ticks by using the `my_formatter` function. This should produce a plot with times on the x-axis and with points colored by a third array. Did you try running the code snippet above? You cannot use `scatter` and `df['x']`, so you need to use a workaround like the one I suggested. – Angus Williams Sep 21 '16 at 10:46
  • Ok I got it! Thank you very much – Kil.Th Sep 21 '16 at 10:55
  • Great - no problem. I'd be appreciative if you accepted my answer if it solved your problem. – Angus Williams Sep 21 '16 at 10:56
  • I will do it definitely. I was just trying out :) – Kil.Th Sep 21 '16 at 10:59
  • I am a beginner in python so sorry for this question but if I have a given list of date in df['x'] and not a "recipe", how can I do the same? – Kil.Th Sep 21 '16 at 12:00
  • 1
    Ok the example I give should work for any list of times (presuming you want hour:minute as the format, but this could easily be changed) – Angus Williams Sep 21 '16 at 12:58