在循环中内置的Matplotlib barplot有时会将bar放在错误的sp中

2024-05-20 20:26:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我写了一个脚本来建立一个“数字”的地层剖面图,它显示了地形上模拟地点随时间的变化。这个脚本是一个更大项目的一部分,所以现在我随机生成高程变化(每年一次)。总之,我可以生成一个很好的数据帧,所有的地层数据格式都正确,我想用这些数据绘制一个图,显示地层是如何随时间变化的。时间应在X轴上,地层厚度应在Y轴上,不同的地层应以颜色显示。我认为这样做的方法是在一个循环中建立一系列条形图,并从最后一层到第一层覆盖它们。所以我把它编码了,并在模拟过程中把地层的厚度绘制成条形图。从最年轻的阶层到最老的阶层,这确实使我要寻找的情节。问题是,在最后一年左右的时间里,酒吧常常会莫名其妙地放在第五年。这种情况似乎每四五次我运行一次脚本。我似乎不知道为什么会这样,我已经检查了我能想到的一切。我显然需要另一双眼睛在这里,我想知道是否有人能明白为什么会发生这种事?我附上an output figure that shows the problem。下面是代码,标记了问题出现的地方。在

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

############### SET UP INIT VALUES ##############
RunLength = 100 # Number of simulated "years"
initdepth = 1.5 # start with some depth (real script will read in from year 0 soildepth map)
prefix = "test2"
#################################################
#### Make some dummy erosion/deposition data ####
di = {k:np.random.normal(0.0075, 0.1, RunLength+1) for k in ["Delta"]} #random normal for elev change
di.update({y:np.arange(RunLength+1) for y in ["Year"]}) # set up column for years (0 to RunLength)
layers = pd.DataFrame(di) # make it into a dataframe
layers['Delta'][0] = 0 #set year 0 to have no change in all the columns
layers["Cumsum"] = layers.Delta.cumsum()+initdepth # calculate cumulative sum, and put it in a column in
layers.set_index('Year', inplace = True) # move the "Year" column to be the index
layers.T.to_csv("%s_CumED.csv" % prefix) # write out csv for posterity, and so we check out work
#####################################################################
### Assemble stratigraphic profile from erosion/deposition events ###
stratigraphy = pd.DataFrame({y:np.arange(RunLength+1) for y in ["Year"]}) #set up new dataframe to contain results of stratigraphic simulation
stratigraphy["Stratum0"] = initdepth # add a column for the base soil (stratum 0)
for idx, row in layers.iterrows(): # run a loop through the stratagraphic data to make "real" layers 
    if idx == 0: # Set up the pre-run soil-depth
        stratigraphy["Stratum0"][idx:RunLength+1] = initdepth # save current depth at this year for the stratum (and fill forward in time)
        old_delta = 0 # set up "old_delta" variable
        stratum = 0 # set up "stratum" variable
        currentdepth = initdepth
    else:
        currentdepth += row['Delta'] # figure out where the surface is this year
        if row['Delta'] >= 0: # Deposition happened this year...
            if old_delta >= 0: # ...and deposition happened last year too.
                stratigraphy["Stratum%s" % stratum][idx:RunLength+1] = currentdepth # continue building current stratum
            else: # ...but erosion happened last year.
                stratum += 1 # make new stratum
                stratigraphy["Stratum%s" % stratum] = 0.0 # add a column for the new stratum
                stratigraphy["Stratum%s" % stratum][idx:RunLength+1] = currentdepth # begin building new stratum
        else: # Erosion happened this year...
            for key in stratigraphy.keys(): #loop through strata
                if stratigraphy[key][idx] > currentdepth: # do we need to erode an old stratum?
                    stratigraphy[key][idx:RunLength+1] = currentdepth #erode!
        old_delta = row["Delta"]
##################################################################
### Make a plot showing how the stratigraphy changes over time ###
plt.ioff() # explicitly set interactive plotting off
sns.set_style("ticks") # set plot style with seaborn
sns.set_context("poster", font_scale = 1.1)
colors = sns.cubehelix_palette(stratum + 1, start=.75, rot=1.5, dark=.25) # grab nice cube helix color palette
fig, ax = plt.subplots(figsize=(17, 8)) #make blank plot with wide aspect ratio
ax.set_autoscale_on(False) # not sure if this doesn anything
### PROBLEM SEEMS TO BE HAPPENING IN HERE
for strat in reversed(range(stratum+1)): # loop through the strata, and overlay them on the plot
    ax.bar(stratigraphy.Year, stratigraphy.ix[:,strat+1], width=1, linewidth=0, color=colors[strat], label="Stratum %s" % strat) # this makes a new overlay for each strata across the years
### /PROBLEM    
ax.plot(layers.Delta.cumsum()+initdepth, color='black', drawstyle="steps-post") # plot a line of where the ground surface has been over time
ax.plot((0, np.amax(stratigraphy.Year)), (np.amax(stratigraphy.ix[:,stratum + 1]), np.amax(stratigraphy.ix[:,stratum + 1])), color='grey', linestyle='dashed') # plot a horizontal line for modern day surface
ax.set_xlim(0,np.amax(stratigraphy.Year)+2) # set limit of X axis a little larger to show last value
ax.set_ylim(0,np.amax(np.amax(stratigraphy.ix[:,1:stratigraphy.shape[1]]))) # set y axis range to match data range
ax.locator_params(nbins = 8) # set tick interval
plt.xlabel('Year')
plt.ylabel('Thickness of stratigraphic layers (m)')
ax.legend(loc='center left', bbox_to_anchor=(1.015, 0.5), fontsize='small', frameon='True', shadow='True', fancybox='True') # put legend of to right of the plot area
fig.subplots_adjust(left=0.065, right=0.90) #tighten up the layout
sns.despine(fig) # remove extraneous plot ticks
plt.savefig("%s_stratigraphy_stackedbar.png" % prefix, dpi=300) # save plot to file
plt.close()

编辑:添加最小的例子,如下。这是一个link to a sample CSV file to use it with.

^{pr2}$

Tags: thetoinforplotlayersnpplt
1条回答
网友
1楼 · 发布于 2024-05-20 20:26:49

看看你的CSV文件,我可以看到没有年份(我假设是第一行)200,而是一个值1.326197,这意味着最后一列数据将在开始的某个地方绘制出来。大小和位置与图形上的偏移条相匹配。我不知道为什么你偶尔会看到它,然后就看不到了,但是请确保你生成的数据是正确的。令我惊讶的是你们有201个专栏。因为Python从零开始计数,所以我假设这个数字是100的乘法。在

相关问题 更多 >