График с игнорированием отсутствующих данных в matplotlib

Я пытался создать программу, которая отображает частоту использования слова во время чатов WhatsApp между двумя людьми. Например, слово night использовалось пару раз в течение нескольких дней и 0 раз в большинстве дней. График у меня такой

Вот код

word_occurances = [0 for i in range(len(just_dates))]

for i in range(len(just_dates)):
    for j in range(len(df_word)):
        if just_dates[i].date() == word_date[j].date():
            word_occurances[i] += 1

title = person2.rstrip(':') + ' with ' + person1.rstrip(':') + ' usage of the word - ' + word

plt.plot(just_dates, word_occurances, color = 'purple')
plt.gcf().autofmt_xdate()
plt.xlabel('Time')
plt.ylabel('number of times used')
plt.title(title)
plt.savefig('Graphs/Words/' + title + '.jpg', dpi = 200)
plt.show()

word_occurances — это список

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Я хочу, чтобы график соединял только точки, в которых он использовался, показывая всю временную шкалу по оси x. Я не хочу, чтобы график касался 0. Как мне это сделать? Я искал и нашел похожие ответы, но ни один из них не работал так, как я.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
1 542
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам просто нужно найти индексы word_occurances, на которых соответствующее значение больше нуля. При этом вы можете индексировать just_dates, чтобы получить соответствующие даты.

word_counts = []    # Only word counts > 0
dates = []          # Date of > 0 word count
for i, val in enumerate(word_occurances):
    if val > 0:
        word_counts.append(val)
        dates.append(just_dates[i])

Вы можете построить график с базовой гистограммой, чтобы сохранить исходный масштаб.

plt.bar(just_dates, word_occurances)
plt.plot(dates, word_counts, 'r--')

Один из способов решить эту проблему — отобразить на графике только данные, содержащие записи, но пометить все даты, когда имел место разговор, чтобы указать нулевые значения на вашем графике:

from matplotlib import pyplot as plt
import matplotlib.dates as mdates
from matplotlib.ticker import FixedLocator

#fake data generation, this block just imitates your unknown data and can be deleted
import numpy as np
import pandas as pd
np.random.seed(12345)
n = 30
just_dates = pd.to_datetime(np.random.randint(1, 100, n)+18500, unit = "D").sort_values().to_list()
word_occurances = [0]*n
for i in range(10): 
    word_occurances[np.random.randint(n)] = np.random.randint(1, 10)


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

#generate data to plot by filtering out zero values
plot_data = [(just_dates[i], word_occurances[i]) for i, num in enumerate(word_occurances) if num > 0]

#plot these data with marker to indicate each point 
#think 1-1-1-1-1 would only be visible as two points with lines only
ax.plot(*zip(*plot_data), color = 'purple', marker = "o")
#label all dates where conversations took place
ax.xaxis.set_major_locator(FixedLocator(mdates.date2num(just_dates)))
#prevent that matplotlib autoscales the y-axis
ax.set_ylim(0, )
ax.tick_params(axis = "x", labelrotation= 90)

plt.xlabel('Time')
plt.ylabel('number of times used')
plt.title("Conversations at night")
plt.tight_layout()
plt.show()

Пример вывода:

Это может скоро стать довольно занятым со всеми этими метками даты (и может или не может работать с вашими объектами даты и времени в just_dates, которые могут отличаться по структуре от моего примера даты). Другой способ — обозначить каждую беседу vlines:

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

plot_data = [(just_dates[i], word_occurances[i]) for i, num in enumerate(word_occurances) if num > 0]

ax.plot(*zip(*plot_data), color = 'purple', marker = "o")
ax.vlines((just_dates), 0, max(word_occurances), color = "red", ls = "--")
ax.set_ylim(0, )

plt.gcf().autofmt_xdate()
plt.xlabel('Time')
plt.ylabel('number of times used')
plt.title("Conversations at night")
plt.tight_layout()
plt.show()

Пример вывода:

Другие вопросы по теме