I thought this would turn out easy, but I am struggling now for a few hours to animate my seaborn scatter plots iterating over my datetime values.
The x and y variables are coordinates, and I would like to animate them according to the datetime variable, colored by their "id".
My data set looks like this:
df.head(10)
Out[64]:
date id x y
0 2019-10-09 15:20:01.418 3479 353 118
1 2019-10-09 15:20:01.418 3477 315 92
2 2019-10-09 15:20:01.418 3473 351 176
3 2019-10-09 15:20:01.418 3476 318 176
4 2019-10-09 15:20:01.418 3386 148 255
5 2019-10-09 15:20:01.418 3390 146 118
6 2019-10-09 15:20:01.418 3447 469 167
7 2019-10-09 15:20:03.898 3476 318 178
8 2019-10-09 15:20:03.898 3479 357 117
9 2019-10-09 15:20:03.898 3386 144 257
The plot that should be iterated looks like this:
.
Below is a quick example. You might want to fix the axes limits to make the transitions nicer.
import pandas as pd
import seaborn as sns
import matplotlib.animation
import matplotlib.pyplot as plt
def animate(date):
df2 = df.query('date == #date')
ax = plt.gca()
ax.clear()
return sns.scatterplot(data=df2, x='x', y='y', hue='id', ax=ax)
fig, ax = plt.subplots()
ani = matplotlib.animation.FuncAnimation(fig, animate, frames=df.date.unique(), interval=100, repeat=True)
plt.show()
NB. I assumed that date is sorted in the order of the frames
edit: If using a Jupyter notebook, you should wrap the animation to display it. See for example this post.
from matplotlib import animation
from IPython.display import HTML
import matplotlib.pyplot as plt
import seaborn as sns
xmin, xmax = df.x.agg(['min', 'max'])
ymin, ymax = df.y.agg(['min', 'max'])
def animate(date):
df2 = df.query('date == #date')
ax = plt.gca()
ax.clear() # needed only to keep the points of the current frame
ax.set_xlim(xmin, xmax)
ax.set_ylim(ymin, ymax)
return sns.scatterplot(data=df2, x='x', y='y', hue='id', ax=ax)
fig, ax = plt.subplots()
anim = animation.FuncAnimation(fig, animate, frames=df.date.unique(), interval=100, repeat=True)
HTML(anim.to_html5_video())
Related
I have a problem with my plotting.
I want to plot multiple meshes in one graph, and each mesh is marked by label.
This is what the data looks like:
I only could plot 1 mesh. Please help.
this is my code (just one mesh) :
import numpy as np
import pandas as pd
import plotly.graph_objects as go
geob_data = pd.read_csv("Geobody.csv")
x = list(geob_data["X"])
y = list(geob_data["Y"])
z = list(geob_data["Z"])
label = list(geob_data["LABEL"])
fig = go.Figure(data=[go.Mesh3d(x=x, y=y, z=z, color='green',
opacity=1, alphahull=0)])
fig.show()
Your question was code with the understanding that you want to draw two meshes on a 3D graph. The key is to extract and add a graph for each label.
import pandas as pd
import io
data = '''
X Y Z LABEL
500 500 -200 1
500 500 -180 1
505 505 -190 1
495 495 -190 1
495 505 -190 1
505 495 -190 1
400 400 -150 2
400 400 -130 2
405 405 -140 2
395 395 -140 2
395 405 -140 2
405 395 -140 2
'''
geob_data = pd.read_csv(io.StringIO(data), delim_whitespace=True)
import plotly.graph_objects as go
#geob_data = pd.read_csv("Geobody.csv")
x = list(geob_data["X"])
y = list(geob_data["Y"])
z = list(geob_data["Z"])
label = list(geob_data["LABEL"])
fig = go.Figure()
for lbl in geob_data['LABEL'].unique():
df = geob_data.query('LABEL == #lbl')
colors = 'green' if lbl == 1 else 'red'
fig.add_trace(go.Mesh3d(x=df['X'].tolist(),
y=df['Y'].tolist(),
z=df['Z'].tolist(),
color=colors,
opacity=1,
alphahull=0
))
fig.update_layout(
autosize=False,
height=600,
width=600,
)
fig.show()
I want to make a gdp vs life expectancy for Ireland over the course of a few years. I want to plot the first point on a scatter plot, then I want wait a few seconds and have the next point plot.
ax = plt.figure()
for i in year:
plt.scatter(ie_gdp[i], ie_life[i])
plt.draw()
plt.show()
plt.pause(1)
So far this is all I can come up with. However, using JupterLab this plots an individual plot for each point. I've tried looking at animations online, but they all use live data. I already have the datasets cleaned and reay in ie_gdp and ie_life.
%matplotlib inline
fig = plt.figure(figsize = (15,15))
ax = fig.add_subplot(1,1,1)
def animate(i):
xs = []
ys = []
for y in year:
xs.append(ie_gdp[y])
ys.append(ie_life[y])
ax.cla()
ax.scatter(xs,ys)
ani = animation.FuncAnimation(fig, animate, interval = 10000)
plt.show()
Above is my attempt at using animations, but it also doesn't work. I get this error: AttributeError: 'list' object has no attribute 'shape'
Any help would be appreciated.
I'm not sure I understand your intended animation, but I animated the x-axis as year, y-axis as average age, and the size of the scatter plot as GDP value. The sample data is from the data provided by Plotly, so please replace it with your own data.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
#from IPython.display import HTML
#from matplotlib.animation import PillowWriter
# for sample data
import plotly.express as px
df = px.data.gapminder()
ie_df = df[df['country'] == 'Ireland']
ie_df
country continent year lifeExp pop gdpPercap iso_alpha iso_num
744 Ireland Europe 1952 66.910 2952156 5210.280328 IRL 372
745 Ireland Europe 1957 68.900 2878220 5599.077872 IRL 372
746 Ireland Europe 1962 70.290 2830000 6631.597314 IRL 372
747 Ireland Europe 1967 71.080 2900100 7655.568963 IRL 372
748 Ireland Europe 1972 71.280 3024400 9530.772896 IRL 372
749 Ireland Europe 1977 72.030 3271900 11150.981130 IRL 372
750 Ireland Europe 1982 73.100 3480000 12618.321410 IRL 372
751 Ireland Europe 1987 74.360 3539900 13872.866520 IRL 372
752 Ireland Europe 1992 75.467 3557761 17558.815550 IRL 372
753 Ireland Europe 1997 76.122 3667233 24521.947130 IRL 372
754 Ireland Europe 2002 77.783 3879155 34077.049390 IRL 372
755 Ireland Europe 2007 78.885 4109086 40675.996350 IRL 372
fig = plt.figure(figsize=(10,10))
ax = plt.axes(xlim=(1952,2012), ylim=(0, 45000))
scat = ax.scatter([], [], [], cmap='jet')
def animate(i):
tmp = ie_df.iloc[:i,:]
ax.clear()
scat = ax.scatter(tmp['year'], tmp['lifeExp'], s=tmp['gdpPercap'], c=tmp['gdpPercap'], ec='k')
ax.set_xlabel('Year', fontsize=15)
ax.set_ylabel('lifeExp', fontsize=15)
ax.set_title('Ireland(1952-2007)')
return scat,
anim = FuncAnimation(fig, animate, frames=12, interval=1000, repeat=False)
#anim.save('gdp_life.gif', writer='Pillow')
plt.show()
I'm still having troubles to do this
Here is how my data looks like:
date positive negative neutral
0 2015-09 23 6 18
1 2016-04 709 288 704
2 2016-08 1478 692 1750
3 2016-09 1881 926 2234
4 2016-10 3196 1594 3956
in my csv file I don't have those 0-4 indexes, but only 4 columns from 'date' to 'neutral'.
I don't know how to fix my codes to get it look like this
Seaborn code
sns.set(style='darkgrid', context='talk', palette='Dark2')
fig, ax = plt.subplots(figsize=(8, 8))
sns.barplot(x=df['positive'], y=df['negative'], ax=ax)
ax.set_xticklabels(['Negative', 'Neutral', 'Positive'])
ax.set_ylabel("Percentage")
plt.show()
To do this in seaborn you'll need to transform your data into long format. You can easily do this via melt:
plotting_df = df.melt(id_vars="date", var_name="sign", value_name="percentage")
print(plotting_df.head())
date sign percentage
0 2015-09 positive 23
1 2016-04 positive 709
2 2016-08 positive 1478
3 2016-09 positive 1881
4 2016-10 positive 3196
Then you can plot this long-format dataframe with seaborn in a straightforward mannter:
sns.set(style='darkgrid', context='talk', palette='Dark2')
fig, ax = plt.subplots(figsize=(8, 8))
sns.barplot(x="date", y="percentage", ax=ax, hue="sign", data=plotting_df)
Based on the data you posted
sns.set(style='darkgrid', context='talk', palette='Dark2')
# fig, ax = plt.subplots(figsize=(8, 8))
df.plot(x="date",y=["positive","neutral","negative"],kind="bar")
plt.xticks(rotation=-360)
# ax.set_xticklabels(['Negative', 'Neutral', 'Positive'])
# ax.set_ylabel("Percentage")
plt.show()
I'm having a data-frame as follows:
match_id team team_score
411 RCB 263
7937 KKR 250
620 RCB 248
206 CSK 246
11338 KKR 241
61 CSK 240
562 RCB 235
Now, I want to plot a bar plot for all these values as an individual bars, what I'm getting in output is something different:
Is there any way I can make different bars for same x-axis values??
When 'team' is used as x, all the values for each team are averaged and a small error bar shows a confidence interval. To have each entry of the table as a separate bar, the index of the dataframe can be used for x. After creating the bars, they can be labeled with the team names.
Optionally, hue='team'colors the bars per team. Then dodge=False is needed to have the bars positioned nicely. In that case, Seaborn also creates a legend, which is not so useful, as the same information now also is present as the x-values. The legend can be suppressed via ax.legend_.remove().
from matplotlib import pyplot as plt
import pandas as pd
from io import StringIO
import seaborn as sns
data_str = StringIO("""match_id team team_score
411 RCB 263
7937 KKR 250
620 RCB 248
206 CSK 246
11338 KKR 241
61 CSK 240
562 RCB 235""")
df = pd.read_csv(data_str, delim_whitespace=True)
color_dict = {'RCB': 'dodgerblue', 'KKR': 'darkviolet', 'CSK': 'gold'}
ax = sns.barplot(x=df.index, y='team_score', hue='team', palette=color_dict, dodge=False, data=df)
ax.set_xticklabels(df['team'])
ax.legend_.remove()
plt.tight_layout()
plt.show()
I will like to know how I can go about plotting a barchart with upper and lower limits of the bins represented by the values in the age_classes column of the dataframe shown below with pandas, seaborn or matplotlib. A sample of the dataframe looks like this:
age_classes total_cases male_cases female_cases
0 0-9 693 381 307
1 10-19 931 475 454
2 20-29 4530 1919 2531
3 30-39 7466 3505 3885
4 40-49 13701 6480 7130
5 50-59 20975 11149 9706
6 60-69 18089 11761 6254
7 70-79 19238 12281 6868
8 80-89 16252 8553 7644
9 >90 4356 1374 2973
10 Unknown 168 84 81
If you want a chart like this:
then you can make it with sns.barplot setting age_classes as x and one columns (in my case total_cases) as y, like in this code:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('data.csv')
fig, ax = plt.subplots()
sns.barplot(ax = ax,
data = df,
x = 'age_classes',
y = 'total_cases')
plt.show()