Come tracciare un set di dati molto grande (data, ora (asse x) rispetto ai valori registrati (asse y) ogni 15 minuti al giorno per un anno) in Matplotlib

Aug 23 2020

Dovrei preparare un grafico x vs y in Python. Il mio set di dati è composto da data, ora e temperatura che viene registrata in un intervallo di 15 minuti all'anno. Diciamo che ho i dati di un mese e ho provato a tracciarli in Matplotlib. Ricevo un grafico che non è così chiaro perché l'asse x (data-time) è pieno su tutto l'asse e non ottengo un'immagine chiara mentre Excel fornisce una buona trama rispetto a matplotlib.

Il codice che utilizzo per aprire 30 singoli file giornalieri di dati csv registrati e concatenarli per formare un frame di dati è il seguente

import pandas as pd
from openpyxl import load_workbook
import tkinter as tk
import datetime
from datetime import datetime
from datetime import time
from tkinter import filedialog
import matplotlib.pyplot as plt
root = tk.Tk()
root.withdraw()
root.call('wm', 'attributes', '.', '-topmost', True)
files = filedialog.askopenfilename(multiple=True) 
%gui tk
var = root.tk.splitlist(files)
filePaths = []
for f in var:
    df = pd.read_csv(f,skiprows=8, index_col=None, header=0, parse_dates=True, squeeze=True, encoding='ISO-8859–1', names=['Date', 'Time', 'Temperature', 'Humidty']) #, 
    filePaths.append(df)
    df = pd.concat(filePaths, axis=0, join='outer', ignore_index=False, sort=True, verify_integrity=False, levels=None) 
    df["Time period"] = df["Date"] + df["Time"]
    plt.figure()
    plt.subplots(figsize=(25,20))
    plt.plot('Time period', 'Temperature', data=df, linewidth=2, color='g')
    plt.title('Temperature distribution Graph')
    plt.xlabel('Time')
    plt.grid(True)

Esempio di dati

Il grafico di output è simile al seguente:

Come puoi vedere nel grafico di output è fiorito con i punti dati sull'asse x e non è in una forma leggibile. Inoltre, matplotlib fornisce più grafici se carico e concateno file .csv per un gruppo di giorni.

Lo stesso set di dati tracciato in Excel/Libre fornisce un grafico uniforme con date disposte in modo ordinato sull'asse x e anche il grafico a linee è perfetto.

Voglio riscrivere il mio codice per tracciare un grafico simile a quello tracciato in Excel/Libre. Per favore aiuto

Risposte

PeterArk Aug 23 2020 at 21:20

Prova questo approccio:

Utilizza i localizzatori di data per formattare l'asse x con l'intervallo di date richiesto. I localizzatori di date possono essere utilizzati per definire intervalli in secondi, minuti, ...:

  • SecondLocator: individua i secondi
  • MinuteLocator: individua i minuti
  • HourLocator: trova gli orari
  • DayLocator: individua i giorni del mese specificati
  • MonthLocator: individua i mesi
  • YearLocator: individua gli anni

Nell'esempio, utilizzo MinuteLocator, con intervallo di 15 minuti.

Importa matplotlib.datesnelle date di lavoro nei grafici:

import matplotlib.dates as mdates

import pandas as pd
import matplotlib.pyplot as plt

Ottieni i tuoi dati

# Sample data
# Data
df = pd.DataFrame({
    'Date': ['07/14/2020', '07/14/2020', '07/14/2020', '07/14/2020'],
    'Time': ['12:15:00 AM', '12:30:00 AM', '12:45:00 AM', '01:00:00 AM'],
    'Temperature': [22.5, 22.5, 22.5, 23.0]
})

Converti Time periodda stringa a oggetto data:

# Convert data to Date and Time
df["Time period"] = pd.to_datetime(df['Date'] + ' ' + df['Time'])

Definisci mine maxintervallo:

min = min(df['Time period'])
max = max(df['Time period'])

Crea la tua trama:

# Plot

# Create figure and plot space
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot()

Imposta l'intervallo di tempo utilizzando i localizzatori:

# Set Time Interval
ax.xaxis.set_major_locator(mdates.MinuteLocator(interval=15))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))

Imposta le opzioni della trama e la trama:

# Set labels
ax.set(xlabel="Time",
       ylabel="Temperature",
       title="Temperature distribution Graph", xlim=[min , max])

# Plot chart
ax.plot('Time period', 'Temperature', data=df, linewidth=2, color='g')
ax.grid(True)
fig.autofmt_xdate()
plt.show()