28 July 2020

Plotly : подписи у графика и осей

Рассмотрим теперь как подписать оси и график.
Для начала выведем простой график:

fig = go.Figure()
trc2 = go.Scatter(
    x = x, y = y,
    name = 'Scatter sample',
    line = dict(color= 'green', dash='dot'),
    marker_symbol ='diamond-open',
    mode ='markers+lines'
)
fig.add_trace ( trc2 )


В результате получится зеленый пунктирный график с алмазами в качестве маркеров.
А теперь посмотрим что из себя представляет объект холста:

print(fig)

Поскольку если мы просто напишем fig то Юпитер просто выведет еще раз график. Значит надо воспользоваться оператором print.
Вот что у нас получится:


Как можно видеть в словаре для холста есть два основных ключа: data и layout. Т.е. данные и оформление. В данных мы можем видеть все свойства заданной точечной диграммы в том числе и данные по осям Х и Y.
А вот второй ключ для оформления - layout - что-то только  говорит о шаблоне но не более.
Если его тоже вывести вот так:

print(fig.layout.template) 

То получим огромный список форматирования. В том числе будет в конце и такое:



И это примерно то, что нам нужно.
Задать подписи в plotly можно вот так - т.е. обращаясь по словарю:

# подписать ось X - можно через обращение по ключу
fig['layout']['xaxis'].update( title = 'My X axis' )

# подписать ось Y - можно и без скобок
fig.layout.yaxis.update( title = 'My Y axis' )

# подписать весь график
fig['layout'].update( title = 'My Chart' )


Т.е. мы выбираем элемент - от холста идет оформление и далее нужная ось или целиком оформление. Далее к ней применяется метод update который и обнавляет значение по ключу title.
Вот что теперь в оформлении:


А вот как стал выглядеть график:


Аналогичных подписей можно добиться и адресными методами:

fig.update_xaxes( title = 'My new X axis' )
fig.update_yaxes( title = 'My new Y axis' )
fig.update_layout( title = 'My New Chart' )


Что даст следующее:


В результате мы подпишем и сам график и оси.

26 July 2020

Plotly: маркеры, линии и легенды

Продолжим играться с Plotly. Теперь посмотрим как можно поменять стиль линий и маркеров.
Управляет стилием отображения ключ словаря mode. Три основных варианта такие:
- markers  - чисто маркеры
- lines  - чисто линии
- markers+lines - маркеры + линии

Рассмотрим на примере, сначала отобразим чисто маркеры:

trc1 = dict( x = x, y = y )
trc1['name'] = 'Model data'
trc1['type'] = 'scatter' ; trc1['mode']='markers' # чисто маркеры
fig.add_trace ( trc1 )


Вот что у нас получится:


Как можно видеть, мы видим только маркеры. График только один и легенда не отображается.
Однако ничего не мешает и ее отобразить:

fig.update_layout(showlegend=True)


Этот вызов сформирует еще один график и уже с легендой:


Теперь попробуем поиграть с маркерами и для этого зададим режим "линия+маркеры" и сделаем линию черной.
Атрибут для линии - line - представляется в виде словаря, поэтому атрибут color уазазывается уже в нем.
Также изменим легенду:

trc1['mode']='markers+lines'
trc1['line'] =dict(color= 'black') 

trc1['name'] = 'Black lines + markers data'
fig.add_trace ( trc1 )


Во что будет после выполнения:


Как можно видеть, новый график перетер старый, однако это совершенно не страшно - панель легенды интерактивная. Т.е. можно выделить нужные нам графики. Например, вот я выделяю предыдущие данные - Model Data - и пропускаю черный график ( при этом он будет подписан более светлым шрифтом, что означает, что он не выделен ):


Т.е. в случае Plotly можно также идти последовательно добавляя все новые диаграммы, и просто выделять именно их при отображении. Чтобы не запутаться, имеет смысл менять при этом легенду.

Следующим шагом поиграемся с видом маркера. Для изменения вида маркера используется ключ marker_symbol, значение diamond-open означает алмаз без заливки. Для изменения цвета, размеров и толщины применяется ключ marker который задается опять словарем в котором цвет идет по ключу color, размер по ключу size, а вот толщину линии надо опять задавать через словарь

trc1['marker_symbol'] ='diamond-open' 
trc1['name'] = 'Diamond markers data'
trc1['marker'] = dict( line= dict(width= 1), color= 'red', size= 8)
fig.add_trace ( trc1 )


Вот что получается после этого выполнения:


Как можно видеть маркеры теперь стали в виде красных алмазов.

Далее поиграемся со стилем линии, пусть теперь мы будем без маркеров и с пунктирной синей линией.
Стиль линии определяется ключом line который имеет тип словаря:

trc1['line'] = dict(color= 'blue', dash='dot')
trc1['name'] = 'Blue dash lines data'
trc1['mode'] = 'lines'
fig.add_trace ( trc1 )


Вот что получится:


Ровно тоже самое можно сделать и при создании посредством использования не словаря, а через go.Scatter:

trc2 = go.Scatter( x = x, y = y, name = 'Scatter sample' )
trc2['line'] =dict(color= 'green', dash='dot')
trc2['marker_symbol']='diamond-open'
trc2['mode']='markers+lines'
fig.add_trace ( trc2 )


Вот результат:


Как можно видеть, цвет линии используется и маркерами, если не задавать их персонально.

24 July 2020

Plotly, еще о диаграммах: типы и рестарт ядра

Ранее в посте Plotly: о точечных диаграммах я забыл добавить еще один важный параметр при задании диаграммы посредством словаря: тип.
Как было видно, по умолчанию Plotly воспринял ее как точечную диаграмму.
Но если сделать вот так:

trc2['type'] = 'bar'

То диаграмма уже превратится в столбцовую или гистограмму:


И вот тут следует оговориться еще об одной важной функции у Блокнота Юпитера - перезапуску ядра или Kernel Restart. Все дело в том, что блокнотом удобно пользоваться последовательно находя решения, но в случае графики несколько последовательных вызовов могут налагаться друг на друга и поэтому графики будут смешиватся.
Вот живой пример -  в одном блокноте я тренировался для двух постов, поэтому у меня код идет последовательно:


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


Блокнот отобразил первый график и стал не следующую ячейку.
Теперь запускаем ее:


Блокнот еще раз отобразил тот же самый график, поскольку по факту мы добавляем такой же точечный график. Но самое интересное будет с добавлением при помощи словаря:


Как можно видеть: на новом графике столбцы добавились к предыдущему графику и сбоку справа появилась легенда.
Если поставить тип не bar, а scatter - будет тоже самое:


Т.е. второй график добавился к первому - это видно по легенде. А поскольку данные идентичные, то просто лег поверх со своим новым ( красным ) цветом.
Простой способ этого избежать такой:
- сделать перезапуск ядра с очисткой вывода:


- запустить ячейки, пропуская те, что не нужны:


Как можно видеть, я пропустил ячейки, выделенные красным. И поэтому когда я запускаю текущую ячейку с добавлением trc2 то добавляется только один график:


Именно таким же способом и получена гистограмма в начале поста.

18 July 2020

Plotly: о точечных диаграммах

Давайте теперь посмотрим что из себя представляют точечные диаграммы Plotly внутри. Для этого просто выведем содержимое:


Как можно видеть, переменная имеет тип Scatter, а внутри фактически располагается словарь, где для ключей x и y  значения являются array с набором значений.
Если посмотреть на описание метода add_trace в справочном руководстве, то увидим такое:


Второй способ мы сейчас и попробуем. Для разнообразия я создал словарь с одним ключом, а второй добавил потом

trc2 = dict( x = x )
trc2['y'] = y


Вот что получилось:


Т.е. по факту мы получили ту же самую картинку, но создавая описание с помощью словаря.
Для ссылки на руководство я использовал plotly.graph_objects.Figure

17 July 2020

Notepadqq и переносы: реабилитация

Ранее в О написании постов я написал, что в с Notepadqq приходится переносить строки руками.
Так вот - я ошибался. Оказывается там тоже возможность автопереносов.
Берем тот же текст, что и в том примере и вставляем в Notepadqq.
Далее идем в меню View и выбираем там Word Wrap :


после этого получаем нужные нам переносы, которые автоматически меняются при изменении размера окна :


Из плюсов Notepadqq - можно  быстро менять размер шрифта Ctrl + Колесо мышки.


16 July 2020

О написании постов

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

Вставим этот же  выше текст в Notepadqq и вот как он будет выглядеть



Если бы мы редактировали его в  Notepadqq то пришлось бы переносить руками, например так:


А теперь попробуем вставить текст в Blogger из Notepadqq и посмотреть что получится:



Вот уже строка перетащилась не так, как я хотел. При просмотре эта неаккуратность хоть и станет немного другой, но останется:


В свое время я нашел весьма удобную программу для ведения заметок - Zim
На Убунту ее не надо ставить отдельно - достаточно найти в ПО Самой Убунты


Текст можно создавать прямо в ней и при переносе текста именно с переносами все хорошо - я просто копирую текст из Zim:


Далее вставляю в Blogger:


И все хорошо:


Текст равномерно распределился там, где я не хотел его переносить явно.

11 July 2020

Plotly начало

В посте Задача двух осей и четырех графиков - введение вторая картинка была сделана посредством Plotly.
Я, разумеется, знаю как там вставить два набора данных на один график, но чтобы и вам показать и самому разобраться, давайте посмотрим на простых примерах ее потроха.
Для начала мы будем строить только один график, данные мы будем получать также как там, поэтому этот код просто скопируем.

Для  Plotly  нам потребуеются добавочно следующие импорты:

import plotly
import plotly.graph_objects as go


В отличии от matplotlib, где можно сразу нарисовать график вызовом plot, для Plotly требуется небольшая предварительная работа - надо сначала сделать холст или в терминологии Plotly - figure:

fig = go.Figure()

Следующим шагом, мы создаем собственно описание графика, которых хотим добавить. Точечный график в  Plotly назвается "рассеиватель" -  Scatter.  Тут я использую русский перевод, какой используется в Excel  - там график называется диаграммой, а простая - X Y ( Scatter ). Я буд назвать его точечный график или точечный набор данных.
В простом случае в Plotly  он создается так:

trc1 = go.Scatter( x= x, y = y )

Т.е. надо вызвать метод Scatter у  plotly.graph_objects и передать ему данные ( х  и у ).
Теперь его остается добавить к фигуре, чтобы отобразить:

fig.add_trace ( trc1 )


И вот что у нас теперь получилось


Cразу же видно отличие от matplotlib -  график интерактивный - есть панель для работы с ним и если навести на какую-либо точку, то отображаются ее значения абсциссы и ординаты

Разумеется, можно создать все это в одну строчку

go.Figure().add_trace ( go.Scatter( x= x, y = y ) )

Но для более сложных построений имеет смысл сохранять это в переменные.

09 July 2020

Задача двух осей и четырех графиков - маркеры и линии с matplotlib


Рассмотренноые ранее подписи осей и легенды графиков облагораживают графики, однако давайте пойдем еще немножко далее, чтобы привести их в красивый вид: рассмотрим стиль линий и маркеров.
При помощи них мы можем сделать графики еще более читаемыми и понимаемыми.

Вот код:

plt.subplot(211)
# зададим маркер для модели в виде маленького крестика
plt.plot( x,y, label='Model', marker='x')
# зададим маркер для реальных данных как и ранее кружочком
plt.plot( x,yr ,color = 'green', marker='o', label='Real')
plt.xlabel('X')
plt.ylabel('Y', color='red', fontsize=14)
plt.title('First Subplot', color='green', fontsize=14)
plt.legend().set_visible(True)

plt.subplot(212)
plt.plot( x,y2,label='Model', marker='x')
# оставим задание маркера и цвета в старом стиле
plt.plot( x,yr2 ,'bo', label='Real')
plt.xlabel('X')
plt.ylabel('Y2')
plt.title('Second Subplot')
plt.subplots_adjust(hspace=0.70)
plt.legend().set_visible(True)


Что мы увидим при исполнении данного кода ?


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

plt.plot( x,yr ,color = 'green', marker='o', label='Real')

На вот такое:

plt.plot( x,yr ,color = 'green', marker='o', linestyle='None', label='Real')


Т.е. явно указать, что стиль линии - нет линии ( None ) и тогда мы вернемся к тому, что было
 

Стили маркеров можно посмотреть тут  matplotlib.markers
А стили линий  - тут Linestyles

Теперь сделаем для реальных данных разреженные пунктирные линии и для первого графика вместо кружочков - алмазы.
Вот код:

plt.subplot(211)
plt.plot( x,y, label='Model', marker='x')
plt.plot( x,yr ,color = 'green', marker='D', linestyle='dashed', label='Real')
plt.xlabel('X')
plt.ylabel('Y', color='red', fontsize=14)
plt.title('First Subplot', color='green', fontsize=14)
plt.legend().set_visible(True)

plt.subplot(212)
plt.plot( x,y2,label='Model', marker='x')
plt.plot( x,yr2 ,color = 'green', marker='o', linestyle='dashed', label='Real')
plt.xlabel('X')
plt.ylabel('Y2')
plt.title('Second Subplot')
plt.subplots_adjust(hspace=0.70)
plt.legend().set_visible(True)


И вот что получилось


Теперь разделение маркерами и стилями линий позволяет нам отличить модельные данные от реальных данных

04 July 2020

Привет, SQLite!

Я люблю реляционные базы данных. Поэтому вопрос о том, что они мне будут нужны в Убунте и при программировании на Питоне стоял изначально.
И вот я сдвинулся с мертвой точки - поставил SQLite и попробовал с ней поработать в Блокноте Юпитера с Питоном и Пандой.
Был выбран SQLite именно из-за простоты - там база представляет из себя отдельный файл и все просто, не надо никаких хитрых настроек для аутентифиакации или авторизации, заведение пользователей и прочие DBA задачи, которые возникнут если использовать MySQL или PostgreSQL - бери и пользуйся. Для хранения данных при чисто личном доступе для анализа - больше и не надо.

По факту оказалось что и так все нужно было установлено - я поставил только DB Browser for SQLite, причем ставится он прямо из установки ПО для Убунты


Далее я создал простенькую базу с одной таблицей из двух колонок и добавил туда две записи



Далее я сохранил файл, создал папку в Блокноте Юпитера и скопировал файл базы туда, чтобы пользоваться чисто именем файла без пути.

 

Замечание: при сохранении файла в DB Browser for SQLite если чисто указать имя, то файл сохранится без расширения db и потом, когда его требуется открыть, он не виден по-умолчанию в папке и надо менять фильтр с SQLite database files на all files.

Теперь заглянем сюда, где показано как работать с базой в Юпитере Interacting With Your SQLite DB in a Jupyter Notebook и по образцу сделаем код:

# импорты
import pandas as pd
import sqlite3

# соединяемся с базой
conn = sqlite3.connect("test1")

# создаем курсор
cur = conn.cursor()


Проверяем что данные на месте:


# выполняем запрос
cur.execute("select * from test;")

# вытаскиваем все данные и печатаем
results = cur.fetchall()
print(results)



Итак, c данными у нас порядок.
Теперь можно это оправить в Панду:

df = pd.read_sql_query("select * from test", conn)
df




И в заключении закрываем курсор и соединение:

cur.close()
conn.close()


Собственно и все - код простой и все работает как надо.

matplotlib - еще парочку ссылок

По ходу того, как я разбирался с подписями, попалась еще парочка ссылок на английском по matplotlib:




Задача двух осей и четырех графиков - подписи с matplotlib

Ранее в посте Задача двух осей и четырех графиков - игра с matplotlib
я рассмотрел разбиени холста на области и рисование нескольких графиков.
Пойдем дальше - рассмотим всякие подписи и для начала подпишем оси и графики

01 July 2020

Панда - обновляем CSV на облачном файловом хранилище

Чисто интресно было проверить - меняется ли ссылка при обновлении файла ?
Т.е. скажем мы обновили данные и пытаемся обновить файл на облаке, выбрав его замену.
Как показал эксперимент - не меняется. И на google drive и на яндекс-диске.
Т.е. смело можно обновлять и читать питоном уже имеющуюся ссылку.

Чисто для себя - если требуется вывести последние несколько строк, можно использовать отрицательную индексацию, типа такого

df[-7:]

Данная строчка выведет последние семь строчек фрейма Панды. Т.е. от минус семи до конца.