Jakzach
Jakzach

Reputation: 23

Matplotlib plots graph in a very strange way

Trying to plot UV-index over the course of the day. The data comes from an api, which after some treatment gives me the data in a nice list. The plot however is absolutely disgusting. Link to graph. Y-axis values are repeated and thrown around, so there are multiple 0s, positive numbers on both sides of the multiple 0s, and a nightmare to interpret. Thanks in advance

Code:

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()

Upvotes: 2

Views: 217

Answers (3)

yes
yes

Reputation: 261

This fixes everything, and the code is pretty self-explanatory, but ask if you're confused by anything:

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()

uv graph

(Also, check your weather.csv file; it shouldn't be in a csv format since its json data, not table data.)

Upvotes: 2

crayxt
crayxt

Reputation: 2405

As mentioned, your Y data is not of numeric type.

Also that is definitely a new way of parsing json responses. Try this:

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()

As requested, full example. Not sure why result is saved to a text file, but it is json file and not csv one.

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()

Upvotes: 1

dm2
dm2

Reputation: 4275

Your substring is a list of strings. Matplotlib treats strings as discrete values (so there's no difference in distance between '0' and '0.01' and '0' and '1000'; and there's no order between them, so '1000' could appear lower than '0').

Convert your substring to float before plotting:

substring = list(map(float,substring))

Or, since your substring is a numpy array:

substring = substring.astype('float')

Upvotes: 1

Related Questions