Уменьшение плотности значений оси x для дат на морском графике? [обновлено] - PullRequest
1 голос
/ 02 августа 2020

Довольно новичок в python и программировании в целом, так что несите меня, пожалуйста. У меня есть набор данных, импортированный из файла .csv, и я пытаюсь построить столбец значений (ось y) по дате (ось x) за 1 год, но проблема в том, что даты слишком плотные, и я хоть убей не могу понять, как их разделить или изменить то, как они определены. Вот код, с которым я работаю:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib as mpl
from scipy import stats
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt

df = pd.read_csv('Vanuatu Earthquakes 2018-2019.csv')

, а вот код линейного графика:

plt.figure(figsize=(15, 7))
ax = sns.lineplot(x='date', y='mag', data=df).set_title("Earthquake magnitude May 2018-2019")

plt.xlabel('Date')
plt.ylabel('Magnitude (Mw)')
plt.savefig('EQ mag time')

Это в настоящее время дает мне этот линейный график: 1

В настоящее время я хочу сделать это с помощью чего-то вроде маленькой галочки для каждого дня и большей галочки + метки для начала каждой недели. Не обязательно, чтобы это было именно так, но я в основном хочу просто уменьшить плотность. Я просмотрел множество сообщений здесь, но ни один из них, похоже, не работает в моей ситуации, поэтому любая помощь будет принята с благодарностью.

[Обновление]

Даты работают согласно Konqui совет ниже, и мой код теперь выглядит так:

time = pd.date_range(start = '01-05-2018',
                     end = '01-05-2019',
                     freq = 'D')
df = pd.DataFrame({'date': list(map(lambda x: str(x), time)),
                   'mag': np.random.random(len(time))})

plt.figure(figsize=(15, 7))
df['date'] = pd.to_datetime(df['date'], format = '%Y-%m')
ax = sns.lineplot(x='date', y='mag', data=df).set_title("Earthquake magnitude May 2018-2019")
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday = 1))
ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)
ax.xaxis.set_minor_locator(md.DayLocator(interval = 1))
plt.xlabel('Date')
plt.ylabel('Magnitude (Mw)')

, что дает мне сообщение об ошибке: AttributeError: 'Text' object has no attribute 'xaxis'. Есть мысли?

1 Ответ

1 голос
/ 02 августа 2020

Допущение

Я полагаю, вы начинаете с фрейма данных, подобного этому, сохраненному в файле Vanuatu Earthquakes 2018-2019.csv:

import pandas as pd
import numpy as np

time = pd.date_range(start = '01-01-2020',
                     end = '31-03-2020',
                     freq = 'D')
df = pd.DataFrame({'date': list(map(lambda x: str(x), time)),
                   'mag': np.random.random(len(time))})

вывод:

                  date       mag
0  2020-01-01 00:00:00  0.940040
1  2020-01-02 00:00:00  0.765570
2  2020-01-03 00:00:00  0.951839
3  2020-01-04 00:00:00  0.708172
4  2020-01-05 00:00:00  0.705032
5  2020-01-06 00:00:00  0.857500
6  2020-01-07 00:00:00  0.866418
7  2020-01-08 00:00:00  0.363287
8  2020-01-09 00:00:00  0.289615
9  2020-01-10 00:00:00  0.741499

построение :

import seaborn as sns
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize = (15, 7))

sns.lineplot(ax = ax, x='date', y='mag', data=df).set_title('Earthquake magnitude May 2018-2019')

plt.xlabel('Date')
plt.ylabel('Magnitude (Mw)')

plt.show()

enter image description here


Answer

You should do a series of things:

  1. First of all, you get that density of labels because your 'date' values are str type, you need to convert them to datetime by

    df['date'] = pd.to_datetime(df['date'], format = '%Y-%m-%d')
    

    in this way your x axis is a datetime type and the above plot will become this:

enter image description here

  1. Затем необходимо настроить галочки; для основных тиков вы должны установить:

    import matplotlib.dates as md
    
    # specify the position of the major ticks at the beginning of the week
    ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday = 1))
    # specify the format of the labels as 'year-month-day'
    ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
    # (optional) rotate by 90° the labels in order to improve their spacing
    plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)
    

    и для второстепенных:

    # specify the position of the minor ticks at each day
    ax.xaxis.set_minor_locator(md.DayLocator(interval = 1))
    

    при желании вы можете изменить длину тактов с помощью:

    ax.tick_params(axis = 'x', which = 'major', length = 10)
    ax.tick_params(axis = 'x', which = 'minor', length = 5)
    

    , поэтому окончательный график станет:

введите описание изображения здесь

Весь код

# import required packages
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.dates as md

# read the dataframe
df = pd.read_csv('Vanuatu Earthquakes 2018-2019.csv')
# convert 'date' column type from str to datetime
df['date'] = pd.to_datetime(df['date'], format = '%Y-%m-%d')

# prepare the figure
fig, ax = plt.subplots(figsize = (15, 7))

# set up the plot
sns.lineplot(ax = ax, x='date', y='mag', data=df).set_title('Earthquake magnitude May 2018-2019')

# specify the position of the major ticks at the beginning of the week
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday = 1))
# specify the format of the labels as 'year-month-day'
ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
# (optional) rotate by 90° the labels in order to improve their spacing
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)

# specify the position of the minor ticks at each day
ax.xaxis.set_minor_locator(md.DayLocator(interval = 1))

# set ticks length
ax.tick_params(axis = 'x', which = 'major', length = 10)
ax.tick_params(axis = 'x', which = 'minor', length = 5)

# set axes labels
plt.xlabel('Date')
plt.ylabel('Magnitude (Mw)')

# show the plot
plt.show()

Примечания

Если вы обратите внимание на ось y на моих графиках, вы увидите, что значения 'mag' попадают в диапазон (0-1). Это связано с тем, что я генерирую эти поддельные данные с помощью 'mag': np.random.random(len(time)). Если вы прочитаете ваши данные из файла Vanuatu Earthquakes 2018-2019.csv, вы получите правильные значения по оси y. Попробуйте просто скопировать код из раздела Весь код .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...