问题
How can I fill bar graph's bars with image like the pattern does?
The following are my discoveries or related questions:
So far I have find this useful post. It helps me to output a graph like this. This is already very near to what I want.
However, I would like to have this effect like this post. Unfortunately, this is a JS post. I just want to fill the bar with images once it reaches 1, fill twice when it reaches 2 accordingly. And for decimal, it crops the image or just resize it to fit the bar.
And here is my playground code.
from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt
import numpy as np
import imageio
import math
def image_plot(heights, images, spacing=0):
# Iterate through images and data, autoscaling the width to
# the aspect ratio of the image
for i, (height, img) in enumerate(zip(heights, images)):
width = 1
left = width*i
right = left + width
plt.imshow(img, extent=[left, right, 0, height])
# Set x,y limits on plot window
plt.xlim(0, right)
plt.ylim(0, max(heights)*2)
data = {"success": True,
"message": {
"portion": "100g",
"nickname": "",
"trans-fat(g)": "NA",
"carbohydrates(g)": "42",
"type": "breakfast",
"sugar(g)": "14",
"energy(kcal)": "260",
"fat(g)": "7.3",
"fiber(g)": "1.6",
"cholesterol(mg)": "17",
"protein(g)": "7.3",
"Na(mg)": "290",
"name": "Pork Burger"
}
}
msg = data["message"]
x = np.arange(5)
values = [msg["energy(kcal)"], msg["protein(g)"], msg["fat(g)"], msg["sugar(g)"], msg["Na(mg)"]]
values = list(map(float, values))
compare = [457.0,4.68,33.15,34.98,196.38]
values[0] = values[0]/compare[0]
values[1] = values[1]/compare[1]
values[2] = values[2]/compare[2]
values[3] = values[3]/compare[3]
values[4] = values[4]/compare[4]
label = ['energy(kcal)', 'protein(g)', 'fat(g)', 'sugar(g)', 'sodium(mg)']
demaeitcho_img = imageio.imread('./img/damaeitcho.png')
soymilk_img = imageio.imread('./img/soymilk.png')
beefpho_img = imageio.imread('./img/beefpho.png')
coke_img = imageio.imread('./img/coke.png')
luncheonmeat_img = imageio.imread('./img/luncheonmeat.png')
imgs = [demaeitcho_img,soymilk_img,beefpho_img,coke_img,luncheonmeat_img]
image_plot(values, imgs, spacing=0)
plt.xticks(x, ("DemaeItcho","SoyMilk","BeefPho","Coke","LuncheonMeat"), color='orange')
- Do I need to call the "plt.imshow()" for each pictures?
- Is that a must to make all images have the same size to perform a better texture mapping on the bars?
回答1:
After an investigation on the method, to produces the ideal graph would be calling the plt.imshow for multiple times (Thanks for ImportanceOfBeingErnest's hint)
So, result comes first.
Click me to see the effect.
To do this, we need a while loop or a for loop to count how many times we need to do the imshow().
......
for i, (height, img) in enumerate(zip(heights, images)):
......
count = 0
while(count<= var_each_image_count):
# image l.side,r.side, b.side, t.side
plt.imshow(img, extent=[left, right, (count), (count+1)])
count = count + 1
......
Remember do not use plt.bar(), because it will cover a new solid color bar over the images.
However, using this method seems to be not OK to support CROP as cropping an image requires specific coordinates on the image to crop.
来源:https://stackoverflow.com/questions/49525017/fill-images-repeatedly-on-bar-graph-bars-bars-customization