【问题标题】:Matplotlib plots graph in a very strange wayMatplotlib 以一种非常奇怪的方式绘制图形
【发布时间】:2021-06-23 10:12:33
【问题描述】:

尝试绘制一天中的紫外线指数。数据来自一个 api,经过一些处理后,它为我提供了一个不错的列表中的数据。不过剧情实在是太恶心了。 Link to graph。 Y轴值是重复的,到处乱扔,所以有多个0,多个0的两边都是正数,解释起来简直就是一场噩梦。提前致谢

代码:

import requests
import re
from matplotlib import pyplot as plt
import numpy as np

# Get weather information
response = requests.get("https://api.openweathermap.org/data/2.5/onecall?lat=55.583328&lon=13.0&lang=se&exclude=minutely,daily,alerts&units=metric&appid=0f0212703cfecb4699dfc2c7edde950a")

# Save weather information to file
with open("weather.csv", 'w') as file:
    file.write(response.text)

# Opens the file and gets all the values of "uv-index"
with open("Weather.csv", 'r') as text:
    pattern = 'uvi":(.*?),'
    Line = text.read()
    substring = np.array(re.findall(pattern, Line))

# Creates an x-axis as a list with the same size as y-axis
# If they're not the same size, error is given:
# ValueError: x and y must have same first dimension, but have shapes (12,) and (49,)
x_axis = []
for i in range(len(substring)):
    x_axis.append(i)
x_axis = np.array(x_axis)

# Determines size and plots graph
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x_axis, substring)

# Creates labels
plt.title("UV-Index today")
plt.xlabel("Time")
plt.ylabel("UV-Index")

# Saves the plot as image and shows it on screen
plt.savefig("UV-Index" + ".png")
plt.show()

【问题讨论】:

  • 可能是您的y 值不是数字?

标签: python matplotlib graphing


【解决方案1】:

这解决了所有问题,并且代码非常不言自明,但请询问您是否对任何事情感到困惑:

import requests
import re
from matplotlib import pyplot as plt
import numpy as np
import json

response = requests.get("https://api.openweathermap.org/data/2.5/onecall?lat=55.583328&lon=13.0&lang=se&exclude=minutely,daily,alerts&units=metric&appid=0f0212703cfecb4699dfc2c7edde950a")

with open("weather.txt", 'w') as file:
    file.write(response.text)

# this converts the JSON as a string to JSON as a dictionary
dict1 = json.loads(response.text)

y_axis = []
for entry in dict1['hourly']:
    y_axis.append(entry['uvi'])

y_axis = np.array(y_axis)
x_axis = np.array(range(len(x_axis)))

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x_axis, y_axis)

plt.title("UV-Index today")
plt.xlabel("Time (Hours)")
plt.ylabel("UV-Index")

plt.savefig("UV-Index" + ".png")
plt.show()

(另外,请检查您的 weather.csv 文件;它不应该是 csv 格式,因为它是 json 数据,而不是表数据。)

【讨论】:

  • 感谢改进!一直在寻找更好的编码方式。从未使用过 json,但这显然是一种更好的方法。
  • 没问题。是的,通常当您调用 API 时,它会为您提供 JSON 数据,因此它是一件值得学习的好东西。顺便说一句,我刚刚意识到轴是错误的方向,但它现在固定了:)
【解决方案2】:

您的substring 是一个字符串列表。 Matplotlib 将字符串视为离散值(因此 '0' 和 '0.01' 以及 '0' 和 '1000' 之间的距离没有区别;并且它们之间没有顺序,因此 '1000' 可能会低于 '0')。

在绘图之前将您的substring 转换为浮动:

substring = list(map(float,substring))

或者,因为你的子字符串是一个 numpy 数组:

substring = substring.astype('float')

【讨论】:

    【解决方案3】:

    如前所述,您的 Y 数据不是数字类型。

    这绝对是一种解析 json 响应的新方法。试试这个:

    import json
    s = json.loads(response.text)
    df = pd.json_normalize(s['hourly'])
    df['dt'] = pd.to_datetime(df['dt'], unit='s')
    df.plot(x="dt", y='uvi')
    # Creates labels
    plt.title("UV-Index today")
    plt.xlabel("Time")
    plt.ylabel("UV-Index")
    plt.show()
    

    根据要求,完整示例。不知道为什么将结果保存到文本文件中,但它是 json 文件而不是 csv 一个。

    import requests
    from matplotlib import pyplot as plt
    import json
    import pandas as pd
    import numpy as np
    
    # Get weather information
    response = requests.get("https://api.openweathermap.org/data/2.5/onecall?lat=55.583328&lon=13.0&lang=se&exclude=minutely,daily,alerts&units=metric&appid=0f0212703cfecb4699dfc2c7edde950a")
    
    # Save weather information to file
    with open("weather.json", 'w') as file:
        file.write(response.text)
    
    # Evaluate JSON string to JSON object
    s = json.loads(response.text)
    
    # Create DataFrame with hourly data
    df = pd.json_normalize(s['hourly'])
    
    # Convert time stamps to actual datetime values
    df['dt'] = pd.to_datetime(df['dt'], unit='s')
    
    # Determines size and plots graph
    df.plot(x="dt", y='uvi', figsize=(10, 6))
    
    # Creates labels
    plt.title("UV-Index today")
    plt.xlabel("Time")
    plt.ylabel("UV-Index")
    
    # Saves the plot as image and shows it on screen
    plt.savefig("UV-Index" + ".png")
    plt.show()
    

    【讨论】:

    • 不确定我是否遵循,之前没有使用过请求或 json,所以我很迷茫。首先:我会把这些放在哪里。我了解导入和我自己的代码,但这些变量名没有帮助;)。二、什么是pd?当我把它放在我自己的代码中时,我得到了一个错误。看来你想用一天中的实际时间代替我的时间,对吗?
    • @Jakzach 答案已更新。 pd 表示 pandas 库的常见导入名称,我在第一次 sn-p 时错过了它。我已将 cmets 放在需要的地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 2013-03-23
    相关资源
    最近更新 更多