I generate a graph like this, it measures the content of a transparent tube but the edges of the tube appear like that, you can see the peaks on the edges of the tube... Any suggestion on how to avoid this "extra" peaks? Any suggestion is welcome.
The image of the tube is this one
This is in fact not a matplotlib-specific question. From my understanding of your question, you would like to keep red peaks while remove blue ones. This task can be done by scipy.signal.find_peaks, you can specifiy a height value to control the peaks the algorithm finds. Here are some minimum code (adapted from scipy docs):
import matplotlib.pyplot as plt
from scipy.misc import electrocardiogram
from scipy.signal import find_peaks
x = electrocardiogram()[2000:4000]
peaks, _ = find_peaks(x, height=0.5)
fig, ax = plt.subplots(1, 1, figsize=(7.2, 7.2))
ax.plot(x)
ax.plot(peaks, x[peaks], "x")
ax.axhline(y=0.5, ls="--", color="gray")
Related
When I run the code below in a Jupyter Notebook,
I get a map of the world, colored in red.
There are fine white-ish lines between the countries.
Is there a way to plot the world so that all countries
are solid and there's no line in between?
I'm asking, because my real world usecase is a fine grid that
behaves just like the world map: Each grid shape has a fine outline
which I do not want to have in the plot. (Update, since this was asked: The grid shapes will not have the same fill color.
)
import geopandas as gpd
import geoplot as gplt
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
world['total'] = 1
world.plot(column='total', cmap='Set1')
For the grid example, the grid files are at https://opendata-esri-de.opendata.arcgis.com/datasets/3c1f46241cbb4b669e18b002e4893711_0
A simplified example that shows the problem.
sf = 'Hexagone_125_km/Hexagone_125_km.shp'
shp = gpd.read_file(sf)
shp.crs = {'init': 'epsg:4326'}
shp['sum'] = 1 # for example, fill sum with something
shp.plot(figsize=(20,20), column='sum', cmap='gnuplot', alpha=1, legend=True)
The white lines are due to antialiasing. This usually makes the visual more smooth, but leads to white lines in between different shapes. You can turn off anialiasing via
antialiased=False
That has the inevitable drawback of the plot looking pixelated.
An alternative is to give the patches an edge with a certain linewidth. The edges should probably have the same color as the faces, so
edgecolor="face", linewidth=0.4
would be an option. This removes the white lines, but introduces a slight "searing" effect (You'll notice mainly looking at islands like Indonesia or Japan). This will be the more noticable, the smaller the features, so it may be irrelevant for showing a hexbin plot. Still, playing a bit with the linewidth might improve the result further.
Code for reproduction:
import numpy as np; np.random.seed(42)
import geopandas as gpd
import matplotlib.pyplot as plt
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
world['total'] = np.random.randint(0,10, size=len(world))
fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, figsize=(7,10))
world.plot(column='total', cmap='Set1', ax=ax1)
world.plot(column='total', cmap='Set1', ax=ax2, antialiased=False)
world.plot(column='total', cmap='Set1', ax=ax3, edgecolor="face", linewidth=0.4)
ax1.set_title("original")
ax2.set_title("antialiased=False")
ax3.set_title("edgecolor='face', linewidth=0.4")
plt.tight_layout()
plt.savefig("world.png")
plt.show()
I put multiple heatmaps in one figure with matplotlib. I cannot layout it well. Here is my code.
import matplotlib; matplotlib.use('agg')
import matplotlib.pyplot as plt
import numpy as np
x = np.random.rand(6,240,240)
y = np.random.rand(6,240,240)
t = np.random.rand(6,240,240)
plt.subplots_adjust(wspace=0.2, hspace=0.3)
c=1
for i in range(6):
ax=plt.subplot(6,3,c)
plt.imshow(x[i])
ax.set_title("x"+str(i))
c+=1
ax=plt.subplot(6,3,c)
plt.imshow(y[i])
ax.set_title("y"+str(i))
c+=1
ax=plt.subplot(6,3,c)
plt.imshow(t[i])
ax.set_title("t"+str(i))
c+=1
plt.tight_layout()
plt.savefig("test.png")
test.png looks like this.
I want to
make each heatmap bigger
reduce the margin between each heatmaps in row.
I tried to adjust by "subplots_adjust", but it doesn't work.
Additional information
According to ImportanceOfBeingErnest's comment, I removed tight_layout(). It generated this.
It makes bigger each heatmap, but titles overlappes on subplots. And I still want to make each heatmap more bigger, and I want to reduce the margin in row.
Say there are two datasets: a big "background" set, and much smaller "foreground" set. The foreground set comes from the background, but might be much smaller.
I am interested in showing the entire background distribution in an ordered sns.barplot, and have the foreground set a brighter contrasting color to draw attention to these samples.
The best solution I could find is to display one graph on top of the other, but what happens is the graph shrinks down to the smaller domain. Here's what I mean:
import matplotlib.pyplot as plt
import seaborn
# Load the example car crash dataset
crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
# states of interest
txcahi = crashes[crashes['abbrev'].isin(['TX','CA','HI'])]
# Plot the total crashes
f, ax = plt.subplots(figsize=(10, 5))
plt.xticks(rotation=90, fontsize=10)
sns.barplot(y="total", x="abbrev", data=crashes, label="Total", color="lightgray")
# overlay special states onto gray plot as red bars
sns.barplot(y="total", x="abbrev", data=txcahi, label="Total", color="red")
sns.despine(left=True, bottom=True)
This data produces:
But it should look like this (ignore stylistic differences):
Why doesn't this approach work, and what would be a better way to accomplish this?
A seaborn barplot just plots the its n data along the values of 0 to n-1. If instead you'd use a matplotlib bar plot, which is unit aware (from matplotlib 2.2 onwards), it'll work as expected.
import matplotlib.pyplot as plt
import seaborn as sns
# Load the example car crash dataset
crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
# states of interest
txcahi = crashes[crashes['abbrev'].isin(['TX','CA','HI'])]
# Plot the total crashes
f, ax = plt.subplots(figsize=(10, 5))
plt.xticks(rotation=90, fontsize=10)
plt.bar(height="total", x="abbrev", data=crashes, label="Total", color="lightgray")
plt.bar(height="total", x="abbrev", data=txcahi, label="Total", color="red")
sns.despine(left=True, bottom=True)
The title explains it all. I don't know what I am doing wrong.
Based on the piece of code you provided, this snippet below should achieve what you want. The idea is to provide manually the bins location, set the width of each bar and align everything left. More information here.
import matplotlib.pyplot as plt
import numpy
columnList = []
for i in range(32):
columnList.append('Asia')
for i in range(58):
columnList.append('Europe')
for i in range(18):
columnList.append('North America')
for i in range(12):
columnList.append('Central or\nSouth America')
for i in range(7):
columnList.append('Australia or\nOceania')
n, bins, patches = plt.hist(x=columnList, bins=numpy.arange(6), rwidth=0.5,
align='left')
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Continents')
plt.ylabel('Frequency')
plt.title('Continental Distribution of respondents')
plt.show()
I'm plotting a simple heatmap with a skewed distribution of values
import numpy as np
import matplotlib.pyplot as plt
import random
import matplotlib
size=100
data=np.array([[random.expovariate(1) for _ in range(size)] for _ in range(size)])
fig, ax=plt.subplots()
heatmap=ax.pcolormesh(data, cmap=matplotlib.cm.Reds)
fig.colorbar(heatmap)
It would be great, if I could change the color scaling such that values below some threshold are a fixed color (for example lowest color in the cmap) and all other values are scaled to show a more uniform distribution of colors (for example exponential or power rescaling with some parameter).
Is there an easy way to rescale my colormap without changing my data values?
If you are happy with a linear bit of the scale, there is:
heatmap=ax.pcolormesh(data, cmap=matplotlib.cm.Reds, vmin=0, vmin=1)
Now the colors are scaled form 0 to 1.
If you want to have a non-linear colormap, it is possible, as well. In order to get it and the respective color bar correct, you'll need to jump through some hoops.
The accepted answer to nonlinear colormap, matplotlib should give you the recipe.