I would like to customize the x axis of a pyplot line chart. Basically, I have periods without values, so I want to skip these periods.
Data example:
Row
x
y
previous
2021-5-10 14:58
100.520
previous
2021-5-10 14:59
100.500
red dot
2021-5-10 15:00
100.550
green dot
2021-5-11 9:00
100.490
after
2021-5-11 9:01
100.650
after
2021-5-11 9:02
100.480
def chartValueTimeLine(time_series, value_series, line_color='blue', time_label='date', value_label='y_label', alpha_value=0.35, title='chart1'):
fig = plt.figure(figsize=(12.5, 7), num=title)
fig.subplots_adjust(bottom=0.2)
plt.plot(time_series, value_series, label=value_label, color = line_color, alpha=alpha_value)
plt.title(title)
plt.xticks(rotation=45)
plt.xlabel(time_label)
plt.ylabel(value_label)
plt.legend(loc='upper left')
I would like the green point to come directly after the red one in the x-axis. Does anyone know how to do this?
Thanks
Related
I'm trying to plot a bar graph that is accompanied by two line graphs. The barplot shows fine but I can't seem to get the lines plotted above the barplot. Here's the code:
fig, ax = plt.subplots(figsize=(18,9))
sns.set_style("darkgrid")
g=sns.barplot(date_new, df["Net xG (xG - Opponent's xG)"].astype("float"), palette="coolwarm_r", hue=df["Net xG (xG - Opponent's xG)"].replace({"-":0}).astype("float"), dodge=False, data=df)
plt.plot(date_new, -df["Opponent's xG"].astype("float"), color="gold", marker="o")
plt.plot(date_new, df["xG (Expected goals)"].astype("float"), color="indianred", marker="o")
g.set_xticklabels(stuff[::-1], rotation=90)
g.get_legend().remove()
g.set(xlim=([-0.8, 46]))
plt.show()
date_new variable used for the x-axis is in datetime64[ns] format. A weird thing I noticed is that if I reformat date_new as a string like date_new.astype("str"), the line plots show but the order is reversed.
I tried to "re-reverse" the order of which dates are sorted by by changing the x-axis variable to date_new[::-1], but that doesn't seem to change the line plots' order.
Here's a screenshot of how the x (Date) and y (xG) axis variables look on the dataframe:
You are trying to combine a bar graph with two line plots. It seems you are having issues matching your x-axis variables. As #Henry Ecker said above, the x axis labels on a bar plot are cosmetic and do not represent an actual date time axis. Consequently, the x-axis values for your bar plot are simply the numbers 0 to 46.
To fix your problem, simply make the line plot x values a list from 0 to 46.
I simulated your data and demonstrate the solution in the example below.
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
# create data
# there are 46 rows each representing a game against some other club
# colums include: date of game, opposing club, club goals, opposing club goals
# goal range is 0-5
df = pd.DataFrame({
'date':pd.date_range(start='1/2021', end='7/1/2021', periods=46),
'club':['Team: ' + str(n) for n in range(1,47)],
'goals': np.random.randint(0, 5, 46),
'opposing_goals':np.random.randint(0, 5, 46)
})
df['net_goals'] = df.goals - df.opposing_goals
fig, ax = plt.subplots(figsize=(18,9))
sns.set_style("darkgrid")
g=sns.barplot(
x=df.date, y=df.net_goals,
palette="coolwarm_r", hue=df.net_goals, dodge=False, data=df
)
plt.plot(np.arange(0,46), -df.opposing_goals, color="gold", marker="o")
plt.plot(np.arange(0,46), df.goals, color="indianred", marker="o")
g.set_xticklabels(df.club, rotation=45)
g.get_legend().remove()
g.set(xlim=([-0.8, 46]))
I m trying to replicate this boxplot with seaborn. I wish to have a division like in the image. I thought that I can create a different Boxplot and union in a single image but isn't a great idea for computation, create many images, use a merge and delete all.
I used Seaborn to put the value on the box in this way
this is my function:
def boxplot(df, name,prot,min,max):
fig = plt.figure(figsize=(100, 20))
plt.title(name+ " RMSE from "+ str(min) +"h PSW to " + str(max) +"h PWS")
plt.ylabel("RMSE")
plt.xlabel("")
box_plot = sns.boxplot(x="Interval" ,y="RMSE", data=df, palette="Set1", showfliers = False)
ax = box_plot.axes
lines = ax.get_lines()
categories = ax.get_xticks()
for cat in categories:
# every 4th line at the interval of 6 is median line
# 0 -> p25 1 -> p75 2 -> lower whisker 3 -> upper whisker 4 -> p50 5 -> upper extreme value
y = round(lines[4+cat*5].get_ydata()[0],3)
ax.text(
cat,
y,
f'{y}',
ha='center',
va='center',
fontweight='bold',
size=70,
color='white',
bbox=dict(facecolor='#445A64'))
box_plot.figure.tight_layout()
plt.savefig("output/"+str(prot)+ str(name)+".jpg")
plt.close(fig)
I added this code too for each colour (foolish) to set the same colour for each same elements in the box. Ad example for values "15" on the x-axe I set red, and so on...
for i in range(0,len(box_plot.artists),12):
mybox = ax.artists[i]
mybox.set_facecolor('red')
for i in range(1,len(box_plot.artists),12):
mybox = ax.artists[i]
mybox.set_facecolor('orange')
I tried to use a "hue" for the category in my dataset (adding a row 15,30 near various values) but when use hue the boxplot take so many distances between them like this and I really don't like.
I tried to use "order" as same but didn't work.
This kind of plot is called "facetting" when you have a plot that's repeated for different levels of a categorical variable. In seaborn, you can create a FacetGrid, or use catplot to do this kind of things. With a bit of tweaking, you get a result that's very similar to your desired output
# dummy data
N=100
psws = [3,6,12,24,36]
times = [15,30,45,60]
df = pd.DataFrame(columns=pd.MultiIndex.from_product([psws,times], names=['PSW','Time']))
for psw in psws:
for time in times:
df[(psw,time)] = np.random.normal(loc=time, size=(N,))
# data need to be in "long-form"
df = df.melt()
g = sns.catplot(kind='box', data=df, x='Time', y='value', col='PSW', height=4, aspect=0.5, palette='Greys')
g.fig.subplots_adjust(wspace=0)
# remove the spines of the axes (except the leftmost one)
# and replace with dasehd line
for ax in g.axes.flatten()[1:]:
ax.spines['left'].set_visible(False)
[tick.set_visible(False) for tick in ax.yaxis.get_major_ticks()]
xmin,xmax = ax.get_xlim()
ax.axvline(xmin, ls='--', color='k')
I am looking to add a shaded box to my plot below. I want the box to go from Aug 25-Aug 30 and to run the length of the Y axis.
The following is my code for the two plots I have made...
df = pd.read_excel('salinity_temp.xlsx')
dates = df['Date']
sal = df['Salinity']
temp = df['Temperature']
fig, axes = plt.subplots(2, 1, figsize=(8,8), sharex=True)
axes[0].plot(dates, sal, lw=5, color="red")
axes[0].set_ylabel('Salinity (PSU)')
axes[0].set_title('Salinity', fontsize=14)
axes[1].set_title('Temperature', fontsize=14)
axes[1].plot(dates, temp, lw=5, color="blue")
axes[1].set_ylabel('Temperature (C)')
axes[1].set_xlabel('Dates, 2017', fontsize=12)
axes[1].xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%b %d'))
axes[0].xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%b %d'))
axes[1].xaxis_date()
axes[0].xaxis_date()
I want the shaded box to highlight when Hurricane Harvey hit Houston, Texas (Aug 25- Aug 30). My data looks like:
Date Salinity Temperature
20-Aug 15.88144647 31.64707184
21-Aug 18.83088846 31.43848419
22-Aug 19.51015264 31.47655487
23-Aug 23.41655369 31.198349
24-Aug 25.16410124 30.63014984
25-Aug 25.2273574 28.8677597
26-Aug 28.35557667 27.49458313
27-Aug 18.52829235 25.92834473
28-Aug 7.423231661 24.06635284
29-Aug 0.520394177 23.47881317
30-Aug 0.238508327 23.90857697
31-Aug 0.143210364 24.30892944
1-Sep 0.206473387 25.20442963
2-Sep 0.241343182 26.32663727
3-Sep 0.58000503 26.93431854
4-Sep 1.182055098 27.8212738
5-Sep 3.632014919 28.23947906
6-Sep 4.672006985 27.29686737
7-Sep 5.938766377 26.8693161
8-Sep 9.107671159 26.48963928
9-Sep 8.180587303 26.05213165
10-Sep 6.200532091 25.73104858
11-Sep 5.144526191 25.60035706
12-Sep 5.106032451 25.73139191
13-Sep 4.279492562 26.06132507
14-Sep 5.255868992 26.74919128
15-Sep 8.026764063 27.23724365
I have tried using the rectangle function in this link (https://discuss.analyticsvidhya.com/t/how-to-add-a-patch-in-a-plot-in-python/5518) however can't seem to get it to work properly.
Independent of your specific data, it sounds like you need axvspan. Try running this after your plotting code:
for ax in axes:
ax.axvspan('2017-08-25', '2017-08-30', color='black', alpha=0.5)
This will work if dates = df['Date'] is stored as type datetime64. It might not work with other datetime data types, and it won't work if dates contains date strings.
I've got an csv file, which contains five days of data, everything is set in few columns. The problem was that every measurement was set every 5 minutes, so during one day I have 288 rows, which for 5 days is 1440 and it goes like this (0:00, 0:05, 0:10 ...).
I used this code to plot everything in one plot, but somehow aranging xticks doesn't work properly.
Here is the code:
fig, ax = plt.subplots(1,1)
ax.set_xticks(x)
ax.set_xticklabels([v for v in data.Time], rotation=45)
ax.plot(x, data.Decfreq)
plt.xticks(np.arange(1, 1440, 60))
Plot I receive:
My data:
00:00 7.680827152169027 0.14000897718551028 7.600809170600135 0.23361947896117427
00:05 7.650820409080692 0.1564676061198724 7.530793436727354 0.2561764164383169
00:10 7.630815913688469 0.15549587808153068 7.540795684423466 0.2576230038042995
00:15 7.820858619914587 0.17966340911411277 7.540795684423466 0.28225658521669184
00:20 7.540795684423466 0.17165693216100902 7.50078669363902 0.2630767707044145
00:25 7.670824904472915 0.13538117325249963 7.390761968981794 0.24547505458369223
00:30 7.84086311530681 0.18094062831351296 7.630815913688469 0.26532083891716435
00:35 7.9608900876601485 0.14987576886445067 7.660822656776803 0.25499025558872285
00:40 7.200719262755675 0.12533028213451503 7.120701281186783 0.23856516035634334
Where only first (time) and second (data) columns interest me.
Implementing code by #Anwarvic I've got this:
As I understood from your comment, the problem is within the label, not the ticks themselves. You need to skip 60 from the data.Time and change set_xticklabels just like so:
fig, ax = plt.subplots(1,1)
ax.set_xticks(x)
values = data.Time.values
ax.set_xticklabels([values[i] for i in range(0, len(values), 60)], rotation=45)
ax.plot(data.Decfreq)
And there is no need for the plt.xticks() part as it's the same as the ax.set_xticks().
EDIT
I don't know how come your plot is far different than mine. Here is my code using this sample data that I created to look exactly like yours:
data = pd.read_csv('sample.csv')
x = np.arange(0, 1440, 60)
fig, ax = plt.subplots(1,1)
ax.set_xticks(x)
# ax.set_xticklabels([v for v in data.Time], rotation=45)
values = data.Time.values
ax.set_xticklabels([values[i] for i in range(0, len(values), 60)], rotation=45)
ax.plot(data.Decfreq)
plt.show()
And here is the plot:
So, my advice is to try changing my csv file with yours with few differences and see if it works
I am plotting a csv read in by pandas using matplotlib and the following code.
Image of CSV data:
fig, ax = plt.subplots(figsize=(10, 10))
plt.plot(dat['Forecast Hour'].iloc[0:45], dat['Forecasted End Time'].iloc[0:45],'b', marker='o')
plt.plot(dat['Forecast Hour'].iloc[0:46], dat['Forecasted Start Time'].iloc[0:46], 'r', marker='o')
bar = plt.bar(dat['Forecast Hour'].iloc[8:46], dat['Forecasted Event Length'].iloc[8:46], width=.8, color='gainsboro')
ax.tick_params(which='major',labelsize='12')
ax.grid(which='major', color='#CCCCCC', linestyle='-')
plt.xticks(rotation='90')
plt.xlabel('Forecast Run')
plt.ylabel('Forecasted Start/End Time')
plt.legend()
ax3 = ax.twinx()
mn, mx = ax.get_ylim()
ax3.set_ylim(0, 12)
ax3.set_ylabel('Forecasted Event Length')
When I try to run the following code I receive the error message:
ValueError: could not convert string to float: '11:00 PM'
When I convert the Nan values to blank spaces using:
dat = dat.replace(np.nan, '', regex=True)
The data will plot but also include the blank space data, like so (space between 9:00 pm and x axis):
Image of Graphed data
Ultimately, how do I a) stop matplotlib from plotting this "blank data" or b) make 9:00 pm the 0 point for my graph axes?
Any help is very much appreciated!