Fill images repeatedly on bar graph bars (bars customization)

蹲街弑〆低调 提交于 2020-06-17 03:40:46

问题


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')
  1. Do I need to call the "plt.imshow()" for each pictures?
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!