lm = sns.lmplot(x='early_mean_zscores', y='late_mean_zscores', col='cat', data=combo)
fig = lm.fig
fig.suptitle("Improvement from Early to Late assignments")
a1 = fig.axes[1]
a1.title("adsadas")
I would like to set the title of the subplots generated by hand, i.e. not based on the col='cat'. This code, and many permutations of it that I have tried don't seem to work.
I don't understand the timing of when the plot is fixed and displayed. Is it on the first line, lm = ... in which case it's not surprising that I cannot, retroactively change the title.
I could use some help on both fixing the code, and a clarification on the sequencing and theory of what is going wrong.
The command to set a title is ax.set_title(). Using that, the code should work as expected.
A minimal example:
import matplotlib.pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
lm = sns.lmplot(x="total_bill", y="tip", col="smoker", data=tips)
fig = lm.fig
fig.suptitle("Custom Super Title")
a1 = fig.axes[1]
a1.set_title("Custom Title")
plt.show()
depending on what you need, you could just use:
lm = sns.lmplot(x="total_bill", y="tip", col="smoker", data=tips).set_titles("{col_name}") # {col_name} is special parameter of actual column name
Related
I'm using pandas, geopandas, and cartopy to make spatial plots for data points.
Everything works fine, except for when I try to add color bar.
Below is my code and the error. Any help is appreciated.
fig = plt.figure()
ax = plt.axes(projection=ccrs.PlateCarree())
reader = shpreader.Reader('countyl010g.shp')
counties = list(reader.geometries())
COUNTIES = cfeature.ShapelyFeature(counties, ccrs.PlateCarree())
ax.add_feature(COUNTIES, facecolor='none', edgecolor='gray')
ax.coastlines()
ax.add_feature(cartopy.feature.STATES)
dp=pd.read_csv('Arash.csv',index_col=False)
def remove_minutes(state):
state=datetime.datetime.strptime(state, '%Y-%m-%d %H:%M:%S')
state= state.replace(minute=0)
return state
dp['TIMESTAMP']=dp['TIMESTAMP'].apply(remove_minutes)
dp.set_index(['TIMESTAMP'], inplace=True)
dp= dp[dp.index.day == 28]
dp['coordinates'] = dp[['Longitude', 'Latitude']].values.tolist()
dp['coordinates'] = dp['coordinates'].apply(Point)
dp = gpd.GeoDataFrame(dp, geometry='coordinates')
ac=dp.plot(ax=ax,column='CO_CMAQ',markersize=0.05,cmap='turbo')
ax.set_xlim(-119,-117)
ax.set_ylim(33.5,34.5)
fig.colorbar(ac,ax=ax)
And here is the error:
File "C:\Python-practice\GHG\spatial_plot_mobile.py", line 102, in
fig.colorbar(ac,ax=ax)
File
"C:\Users\akash\anaconda3\lib\site-packages\matplotlib\figure.py",
line 2343, in colorbar cb = cbar.colorbar_factory(cax, mappable,
**cb_kw)
File
"C:\Users\akash\anaconda3\lib\site-packages\matplotlib\colorbar.py",
line 1734, in colorbar_factory cb = Colorbar(cax, mappable, **kwargs)
File
"C:\Users\akash\anaconda3\lib\site-packages\matplotlib\colorbar.py",
line 1202, in init
if mappable.get_array() is not None: AttributeError: 'GeoAxesSubplot'
object has no attribute 'get_array'
Thank you again,
Old question, but I landed on it because I had an analogous error, so in case it helps anyone else in future:
The problem is that ac here is a GeoAxesSubplot object within a Matplotlib figure. When Matplotlib is given fig.colorbar(ac,ax=ax), it doesn't know what to do with ac.
As per the Geopandas documentation, the information about the colorbar needs to go into the Geopandas .plot() itself, so that the relevant line above would look something like:
ac=dp.plot(ax=ax,column='CO_CMAQ',markersize=0.05,cmap='turbo',
legend=True, legend_kwds={'label':"",'orientation':""})
with the legend_kwds filled in as desired, e.g. orientation="horizontal".
More advice on modifying Geopandas colorbars here.
The following code creates a legend of a facegrid and positions it above:
g = sns.FacetGrid(df, col="col", col_wrap=2, hue='key')
g = g.map(sns.lineplot, 'x', 'y')
g.add_legend()
g._legend.set_bbox_to_anchor((0.5, 1.05))
Is there a way to control the number columns? It has a _ncol attribute but I haven't seen a method to change it. Changing it manually doesn't do the job.
I found the definition of add_legend in the seaborn source code. It accepts **kwargs and hands them to self.figure.legend(...) or ax.legend(...).
So one can simply pass ncol=2 as parameter. This should also be a better was to define the position of the legend by using loc and/or bbox_to_anchor arguments.
Here would is an example:
import seaborn as sns
tips = sns.load_dataset("tips")
g = sns.FacetGrid(tips, col="sex", hue="smoker")
g.map(sns.scatterplot, "total_bill", "tip", alpha=.7)
g.add_legend(ncol=2, bbox_to_anchor=(0.5,1.05));
I appreciate your help;
This part of the code allows me to plot what I want but I need to assign the outcome(a binary image with >500 area objects) to a variable for further processing
Improved_label = np.zeros_like(label_image)
#props = regionprops(label_image)
for R in regionprops(label_image):
if R.area > 500:
# draw the region (I'm sure there's a more efficient way of doing it)
for c in R.coords:
Improved_label[c[0], c[1]] = 1
#Improved_labe1 = Improved_label > 1
Apparently, there is something wrong with the name "improved" at the beginning of the variable name(not sure why). but anyhow, here are two solutions for this issue. I hope this will be helpful for people with the background in Matlab:
-------------Option A--------------
label2_test = np.zeros_like(label_image)
for R in regionprops(label_image):
if R.area > 1000:
# draw the region (I'm sure there's a more efficient way of doing it)
for c in R.coords:
label2_test[c[0], c[1]] = 1
label2_test = label2_test > 0
plt.imshow(labe2_test)
----------------Option B-----------------
from skimage import morphology
labe1_improved = morphology.remove_small_objects(label_image, min_size=1000)
I would like to automatically adjust the width of a bokeh DataTable to the size of a screen. But I do not find the right way to do it. This line of code is supposed to work :
data_table = DataTable(source=source, columns=columns, height = 300, sizing_mode = 'scale_width', fit_columns=True)
But it does not. My Datatable keeps the same width.
Does anyone know how to solve this problem ?
Thank you.
I'm afraid it's not possible with the current implementation of DataTable - if you don't specify an explicit width in pixels, the width will be set to 600px.
You're welcome to create a feature request on Bokeh's GitHub.
As of 2.2.3 and likely earlier you can use sizing_mode:
import pandas as pd, numpy as np, random, string
from bokeh.models import ColumnDataSource, DataTable, TableColumn
from bokeh.plotting import show
df = pd.DataFrame(np.random.randint(0,100,size=(100, 12)), columns=[(random.randint(1,30) * random.choice(string.ascii_uppercase)) for col in range(12)])
data_table = DataTable(columns = [TableColumn(field=c, title=c) for c in df.columns], sizing_mode='stretch_width', source = ColumnDataSource(df))
show(data_table)
I have a tkinter interface with a few entry widgets as inputs. Upon clicking a button I would like those inputs to be sent to a separate script to be processed and a value printed and potentially returned back to the button (I am looking at this for a dual accuracy assessment statistic)
This is a lower scale example of what I have so far and am looking to accomplish
Example Secondary Script: GUI_ConnectorScript
def calculate():
global result
result = int(entry.get())
result += 1
print result
Primary Script: GUI_ConnectorScript
from Tkinter import *
import GUI_ConnectorScript
background = "#A8A8A8"
master = Tk()
screen_width = master.winfo_screenwidth()
screen_height = master.winfo_screenheight()
width = int(screen_width*0.7)
height = int(screen_height*0.7)
size = "%sx%s"%(width,height)
master.geometry(size)
master.title("GIS Display")
text = Text(master, width = 80, height = 40, background = background)
text.pack(expand = TRUE, fill = BOTH)
entry = Entry(master, width=5).place(x=100,y=100)
button = Button(master, text="Calculate", command=GUI_ConnectorScript).place(x=500,y=500)
mainloop()
I have been trying to figure this out for awhile and have look around a lot for an answer. I have found examples similar but I am having an issue getting it to work for my application.
I agree with Parviz, whenever GUI programs get too complicated you should use Object-Oriented Programming.
I can further advice that you use kivy (if possible) instead of tkinter, its much better for bigger projects