matplotlib: построение более чем одной фигуры одновременно - PullRequest
0 голосов
/ 09 января 2020

Я работаю с 3 pandas dataframes, имеющими одинаковую структуру столбцов (номер и тип), только наборы данных для разных лет.

Я хотел бы построить ECDF для каждого из фреймов данных, но каждый раз, когда я делаю это, я делаю это индивидуально (не хватает python навыков). Также, одна из цифр (2018) по-разному масштабируется на x-axis, что затрудняет сравнение. Вот как я это делаю.

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from empiricaldist import Cdf

    df1 = pd.read_csv('2016.csv')
    df2 = pd.read_csv('2017.csv')
    df3 = pd.read_csv('2018.csv')

    #some info about the dfs
    df1.columns.values
    array(['id', 'trip_id', 'distance', 'duration', 'speed', 'foot', 'bike',
       'car', 'bus', 'metro', 'mode'], dtype=object)

    modal_class = df1['mode']
    print(modal_class[:5])
    0         bus
    1         metro
    2         bike
    3         foot
    4         car

    def decorate_ecdf(title, x, y):
        plt.xlabel(x)
        plt.ylabel(y)
        plt.title(title)

    #plotting the ecdf for 2016 dataset
    for name, group in df1.groupby('mode'):
        Cdf.from_seq(group.speed).plot()    
    title, x, y = 'Speed distribution by travel mode (April 2016)','speed (m/s)', 'ECDF'
    decorate_ecdf(title,x,y)

    #plotting the ecdf for 2017 dataset
    for name, group in df2.groupby('mode'):
        Cdf.from_seq(group.speed).plot()    
    title, x, y = 'Speed distribution by travel mode (April 2017)','speed (m/s)', 'ECDF'
    decorate_ecdf(title,x,y)

    #plotting the ecdf for 2018 dataset
    for name, group in df3.groupby('mode'):
        Cdf.from_seq(group.speed).plot()    
    title, x, y = 'Speed distribution by travel mode (April 2018)','speed (m/s)', 'ECDF'
    decorate_ecdf(title,x,y)

Вывод:

enter image description here enter image description here enter image description here

Я почти уверен, что это не питонистский способ сделать это, а грязный способ сделать работу. Вы также можете увидеть, как график 2018 по-разному масштабируется по оси X.

  1. Есть ли способ обеспечить одинаковое масштабирование всех фигур?
  2. Как мне переписать мой код так, чтобы цифры были нанесены путем вызова функции один раз?

1 Ответ

1 голос
/ 10 января 2020

При использовании pyplot вы можете строить неявный метод с помощью plt.plot() или явный метод, создавая и вызывая объекты фигур и осей с помощью fig, ax = plt.subplots(). То, что здесь произошло, на мой взгляд, является побочным эффектом от использования неявного метода.

Например, вы можете использовать две команды pd.DataFrame.plot() и сделать так, чтобы они совместно использовали одну и ту же ось, передав возвращаемую ось другая функция.

foo = pd.DataFrame(dict(a=[1,2,3], b=[4,5,6]))
bar = pd.DataFrame(dict(c=[3,2,1], d=[6,5,4]))
ax = foo.plot()
bar.plot(ax=ax) # ax object is updated
ax.plot([0,3], [1,1], 'k--')

Вы также можете создать объект фигуры и оси ранее, и поставлять по мере необходимости. Кроме того, он идеально подходит для нескольких команд печати. Часто мой код на 25% работает, 75% возится с графиками. Не пытайтесь быть умным и не теряйте удобочитаемость.

fig, axes = plt.subplots(nrows=3, ncols=1, sharex=True)
# In this case, axes is a numpy array with 3 axis objects
# You can access the objects with indexing
# All will have the same x range
axes[0].plot([-1, 2], [1,1])
axes[1].plot([-2, 1], [1,1])
axes[2].plot([1,3],[1,1])

Таким образом, вы можете объединить оба этих фрагмента в свой собственный код. Сначала создайте объект фигур и осей, затем постройте каждый фрейм данных, но предоставьте им правильную ось с ключевым словом ax.

Кроме того, предположим, что у вас есть три объекта оси, и у них разные пределы x , Вы можете получить их все, а затем задать для трех одинаковое минимальное значение и одинаковое максимальное значение. Например:

axis_list = [ax1, ax2, ax3] # suppose you created these separately and want to enforce the same axis limits
minimum_x = min([ax.get_xlim()[0] for ax in axis_list])
maximum_x = max([ax.get_xlim()[1] for ax in axis_list])
for ax in axis_list:
    ax.set_xlim(minimum_x, maximum_x)
...