如何修复在Streamlit应用的Matplotlib折线图中图例条目不匹配的问题?

huangapple go评论98阅读模式
英文:

How can I fix legend entries not matching with my matplotlib line chart on a streamlit app?

问题

以下是您提供的代码的翻译部分:

  1. # Import libraries
  2. import pandas as pd
  3. import streamlit as st
  4. import matplotlib.pyplot as plt
  5. #----------------------- 应力 - 应变-----------------------
  6. # 从源文件加载数据
  7. df = pd.read_excel(
  8. io='MRE.xlsx',
  9. engine='openpyxl',
  10. sheet_name='Sheet1',
  11. skiprows=0,
  12. usecols='A:E',
  13. nrows=11168,
  14. )
  15. # 侧边栏 - 添加可用于筛选的内容
  16. st.sidebar.header('输入应力和应变显示的筛选条件')
  17. spec = st.sidebar.multiselect(
  18. '选择规格:',
  19. options=df['Spec'].unique(),
  20. default=df['Spec'].unique()
  21. )
  22. df_selection = df.query(
  23. 'Spec == @spec'
  24. )
  25. # 绘制数据并添加图例、标题等...
  26. fig = plt.figure()
  27. ax = fig.add_subplot()
  28. df_selection.groupby("Spec").plot(x="平均应变 (%)",
  29. y="平均应力 (MPa)",
  30. legend=False,
  31. ax=ax,
  32. linewidth=0.65,
  33. figsize=(10, 6))
  34. plt.xlabel('应变 (%/100)')
  35. plt.ylabel('应力 (MPa)')
  36. plt.title('应力-应变图')
  37. plt.grid(visible=True)
  38. # 缩小当前轴底部的高度10%
  39. # box = ax.get_position()
  40. # ax.set_position([box.x0, box.y0 + box.height * 0.1,
  41. # box.width, box.height * 0.9])
  42. # 将图例放在当前轴下方
  43. plt.legend(df_selection['Spec'].unique(), loc='upper center', bbox_to_anchor=(0.5, -0.15),
  44. ncol=5)
  45. plt.show()
  46. st.pyplot(fig)

请注意,上述翻译部分仅包括代码,不包括注释和图像的描述。如果您需要更多帮助或有其他问题,请随时提出。

英文:

I want to display a plot in a streamlit app. After selecting the spec in a sidebar widget, I display the selected graphs in a line chart. The problem I have is with the legend. When I select or unselect a spec, the graph is updated correctly but the legend is not.

So for example I have Specs 1 though 5 displayed correctly, but according to the legend Spec 1 is Spec 4, which is not true...

I tried filtering for different things and locating the legend entry at different locations, but that did nothing.
Below is my current code.

  1. # Import libraries
  2. import pandas as pd
  3. import streamlit as st
  4. import matplotlib.pyplot as plt
  5. #----------------------- Stress - Strain-----------------------
  6. # Load data from source file
  7. df = pd.read_excel(
  8. io = 'MRE.xlsx',
  9. engine='openpyxl',
  10. sheet_name='Sheet1',
  11. skiprows=0,
  12. usecols='A:E',
  13. nrows=11168,
  14. )
  15. #SIDEBAR -> add things that can be filtered for
  16. st.sidebar.header('Enter filter for Stress and Strain display')
  17. spec = st.sidebar.multiselect(
  18. 'Select spec:',
  19. options=df['Spec'].unique(),
  20. default=df['Spec'].unique()
  21. )
  22. df_selection = df.query(
  23. 'Spec == @spec'
  24. )
  25. # Plot data and add legend, title, ...
  26. fig = plt.figure()
  27. ax = fig.add_subplot()
  28. df_selection.groupby("Spec").plot(x="Average strain (%)",
  29. y="Average stress (MPa)",
  30. legend=False,
  31. ax=ax,
  32. linewidth = 0.65,
  33. figsize=(10,6))
  34. plt.xlabel('Strain (%/100)')
  35. plt.ylabel('Stress (MPa)')
  36. plt.title('Stress-Strain diagram')
  37. plt.grid(visible=True)
  38. # Shrink current axis's height by 10% on the bottom
  39. # box = ax.get_position()
  40. # ax.set_position([box.x0, box.y0 + box.height * 0.1,
  41. # box.width, box.height * 0.9])
  42. # # Put a legend below current axis
  43. plt.legend(df_selection['Spec'].unique(),loc='upper center', bbox_to_anchor=(0.5, -0.15),
  44. ncol=5)
  45. plt.show()
  46. st.pyplot(fig)

How the legend entry should look like vs. how it actually looks

如何修复在Streamlit应用的Matplotlib折线图中图例条目不匹配的问题?

Sorry, I don't know how to share the data for the df, so I'll share the github link.

答案1

得分: 0

I separated the data, so each spec has their own column. And then I used plt.plot on the new variables instead of the group_by. Seems to work for now.

  1. t = pd.DataFrame();
  2. u = pd.DataFrame();
  3. values = range(0,len(spec));
  4. for i in values:
  5. t[i] = new_df_strain.iloc[:,i];
  6. u[i] = new_df_stress.iloc[:,i];
  7. t2 = t.set_axis(axis = 1, labels = spec, inplace=False);
  8. u2 = u set_axis(axis = 1, labels = spec, inplace=False);
  9. # Plot data and add legend, title, ...
  10. fig = plt.figure();
  11. plt.rcParams['font.size'] = 35;
  12. ax = fig.add_subplot();
  13. plt.plot(t2,
  14. u2,
  15. linewidth = 1.5,);
  16. plt.xlabel('Strain (%)');
  17. plt.ylabel('Stress (MPa)');
英文:

Found a solution that seems to work, at least at the moment. I separated the data, so each spec has their own column. And then I used plt.plot on the new variables instead of the group_by. Seems to work for now.

  1. t = pd.DataFrame();
  2. u = pd.DataFrame();
  3. values = range(0,len(spec));
  4. for i in values:
  5. t[i] = new_df_strain.iloc[:,i];
  6. u[i] = new_df_stress.iloc[:,i];
  7. t2 = t.set_axis(axis = 1, labels = spec, inplace=False);
  8. u2 = u.set_axis(axis = 1, labels = spec, inplace=False);
  9. # Plot data and add legend, title, ...
  10. fig = plt.figure();
  11. plt.rcParams['font.size'] = 35;
  12. ax = fig.add_subplot();
  13. plt.plot(t2,
  14. u2,
  15. linewidth = 1.5,);
  16. plt.xlabel('Strain (%)');
  17. plt.ylabel('Stress (MPa)');

huangapple
  • 本文由 发表于 2023年5月26日 00:01:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76334259.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定