Je voudrais tracer deux dfs
avec deux couleurs différentes. Pour chaque df
, j'aurais besoin d'ajouter deux marqueurs. Voici ce que j'ai essayé:
for stats_file in stats_files: data = Graph(stats_file) Graph.compute(data) data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line') plt.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color='orange') plt.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green') plt.show()
En utilisant ce morceau de code, j'obtiens le servers_df
tracé avec des marqueurs, mais sur des graphiques séparés. Comment puis-je avoir les deux graphiques en un seul pour mieux les comparer?
Merci.
4 Réponses :
DataFrame.plot()
renvoie par défaut un objet matplotlib.axes.Axes
. Vous devez ensuite tracer les deux autres tracés sur cet objet:
colors = ['C0', 'C1', 'C2'] # matplotlib default color palette # assuming that len(stats_files) = 3 # if not you need to specify as many colors as necessary ax = plt.subplot(111) for stats_file, c in zip(stats_files, colors): data = Graph(stats_file) Graph.compute(data) data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line', ax=ax) ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color=c) ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green') plt.show()
Si vous voulez les tracer les uns sur les autres avec des couleurs différentes, vous pouvez faire quelque chose comme ceci:
for stats_file in stats_files: data = Graph(stats_file) Graph.compute(data) ax = data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line') ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color='orange') ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green') plt.show()
Cela change simplement la couleur du servers_df.plot
. Si vous voulez changer la couleur des deux autres, vous pouvez simplement utiliser la même logique: créer une liste de couleurs que vous voulez qu'ils prennent à chaque itération, itérer sur cette liste et transmettre la valeur de color
au paramètre de color
à chaque itération .
Merci pour votre réponse. Si j'utilisais cette partie de code, j'obtiendrais 3 graphiques: 2 vides (dont je suppose que ce seraient les sous-graphiques) et un graphique qui appartiendra au deuxième fichier. Une idée de pourquoi cela arriverait?
Si ax = data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line', ax=ax)
ax = ax dans ax = data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line', ax=ax)
, j'obtiendrais les deux graphiques, mais l'un sous l'autre. Je voudrais les superposer en utilisant différentes couleurs.
Je l'ai un peu changé, voyez si ça aide maintenant :)
Vous pouvez créer un objet Axes
pour le traçage en premier lieu, par exemple
import pandas as pd import numpy as np from matplotlib import pyplot as plt df_one = pd.DataFrame({'a':np.linspace(1,10,10),'b':np.linspace(1,10,10)}) df_two = pd.DataFrame({'a':np.random.randint(0,20,10),'b':np.random.randint(0,5,10)}) dfs = [df_one,df_two] fig,ax = plt.subplots(figsize=(8,6)) colors = ['navy','darkviolet'] markers = ['x','o'] for ind,item in enumerate(dfs): ax.plot(item['a'],item['b'],c=colors[ind],marker=markers[ind])
comme vous pouvez le voir, dans le même ax
, les deux dataframes sont tracés avec des couleurs et des marqueurs différents.
Votre appel à data.servers_df.plot()
crée toujours un nouveau tracé, et plt.plot()
trace sur le dernier tracé créé. La solution est de créer un axe dédié sur lequel tout doit être tracé.
J'ai supposé que vos variables sont les suivantes
data.servers_df
: Dataframe avec deux colonnes flottantes "time"
et "percentage"
data.first_measurements
: Un dictionnaire avec les touches "time"
et "pourcentage", qui sont chacune une liste de flottantsdata.second_measurements
: Un dictionnaire avec les clés "time"
et "percentage"
, qui sont chacune une liste de flottants J'ai sauté la génération de stat_files
car vous n'avez pas montré ce que fait Graph()
, mais j'ai simplement créé une liste de data
factices.
Si data.first_measurements
et data.second_measurements
sont également des dataframes, faites-le moi savoir et il existe une solution encore plus intéressante.
Chaque tracé matplotlib
(ligne, barre, etc.) vit sur un élément matplotlib.axes.Axes
. Ce sont comme des axes réguliers d'un système de coordonnées. Maintenant, deux choses se produisent ici:
plt.plot()
, il n'y a aucun axe spécifié et donc, matplotlib recherche l'élément axes courant (en arrière-plan), et s'il n'y en a pas, il en créera un vide et l'utilisera, et définir est comme défaut. Le deuxième appel à plt.plot()
trouve alors ces axes et les utilise.DataFrame.plot()
d'autre part, crée toujours un nouvel élément axes si aucun ne lui est donné (possible via l'argument ax
) Donc, dans votre code, data.servers_df.plot()
crée d'abord un élément axes derrière les rideaux (qui est alors la valeur par défaut), et les deux appels plt.plot()
obtiennent les axes par défaut et tracent dessus - c'est pourquoi vous obtenez deux parcelles au lieu d'un.
La solution suivante crée d'abord un matplotlib.axes.Axes
dédié à l'aide de plt.subplots()
. Cet élément d'axe est ensuite utilisé pour dessiner toutes les lignes sur. Notez en particulier ax=ax
dans data.server_df.plot()
. Notez que j'ai changé l'affichage de vos marqueurs de o-
à o
(car nous ne voulons pas afficher une ligne ( -
) mais uniquement des marqueurs ( o
)). Des données simulées peuvent être trouvées ci-dessous
import random import pandas as pd import matplotlib.pyplot as plt # Generation of dummy data random.seed(1) NUMBER_OF_DATA_FILES = 2 X_LENGTH = 10 class Data: def __init__(self): self.servers_df = pd.DataFrame( { 'time': range(X_LENGTH), 'percentage': [random.randint(0, 10) for _ in range(X_LENGTH)] } ) self.first_measurement = { 'time': self.servers_df['time'].values[:X_LENGTH // 2], 'percentage': self.servers_df['percentage'].values[:X_LENGTH // 2] } self.second_measurement = { 'time': self.servers_df['time'].values[X_LENGTH // 2:], 'percentage': self.servers_df['percentage'].values[X_LENGTH // 2:] } stat_files = [Data() for _ in range(NUMBER_OF_DATA_FILES)]
fig, ax = plt.subplots() # Here we create the axes that all data will plot onto for i, data in enumerate(stat_files): y_column = f'percentage_{i}' # Make the columns identifiable data.servers_df \ .rename(columns={'percentage': y_column}) \ .plot(x='time', y=y_column, linewidth=1, kind='line', ax=ax) ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o', color='orange') ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o', color='green') plt.show()
Vous devez créer l'intrigue avant. Ensuite, vous pouvez explicitement vous référer à ce graphique lors du traçage des graphiques. df.plot(..., ax=ax)
ou ax.plot(x, y)
import matplotlib.pyplot as plt (fig, ax) = plt.subplots(figsize=(20,5)) for stats_file in stats_files: data = Graph(stats_file) Graph.compute(data) data.servers_df.plot(x="time", y="percentage", linewidth=1, kind='line', ax=ax) ax.plot(data.first_measurement['time'], data.first_measurement['percentage'], 'o-', color='orange') ax.plot(data.second_measurement['time'], data.second_measurement['percentage'], 'o-', color='green') plt.show()
Il semble que votre question concerne le matplotlib et les pandas. Si ce n'est pas le cas, supprimez les balises ajoutées et indiquez les bibliothèques que vous comptez utiliser. Veuillez également fournir un exemple complet comprenant un jeu de données sur les jouets et le résultat attendu.
Quant à la question - il semble que vous devriez créer
fig, ax = plt.subplots()
puis utiliserdata.servers_df.plot(..., ax=ax)
etax.plot(...)
dans votre boucle.