#!/usr/bin/env python # coding: utf-8 # # Введение в Python, настройка среды программирования # Шестаков А.В. Майнор по анализу данных - 12/01/2016 # # Этот IPython Notebook содержит вспомогательные указания для выполнения семинарских и домашних заданий. В течение курса мы будем преимущественно работать в подобных "тетрадках", но может быть иногда будем переключаться на другие среды\средства. # # (Мы используем Python версии 2.x.x, а не 3.x.x) # ## Как установить IPython Notebook у себя дома?! # Самый простой и надежный способ - воспользоваться готовым дистрибутивом [Anaconda](https://store.continuum.io/cshop/anaconda/), включающий в себе практически все необходимые модули и утилиты, которые нам понадобятся - IPython, NumPy, SciPy, Matplotlib и **Scikit-Learn**. Просто следуйте указаниям установщика для вашей ОС. # ## Быстрое введение в Python # ### Калькулятор # In[ ]: 2*7 # In[ ]: 6+4**2-1 # In[ ]: 4^4 # О боже, госпади, что это было? # Знак "\#" символизирует начало комментариев в коде - всё что идет после этого знака до конца строки игнорируется Питоном. # # Поехали дальше - что у нас с делением? # In[ ]: 16/4 # In[ ]: 25/7 # Угадайте, что получится? # Для питона, в результате целочисленного деления должно тоже получится целое число. Т.е. остаток отбрасывается. # Как же намекнуть питону, что мы хотим получить точный ответ? # In[ ]: 25./7 25/7. float(25)/7 # Ну окей, пока всё это можно было посчитать в столбик. # # Есть что посерьезнее? КАААНЕЧНО! # In[ ]: sqrt(4) # ... Но не так сразу. Питон начал ругаться. По-умолчанию, он не знает, что такое извлечение квадратного корня. Однако можно показать ему, где искать. # # В стандартном модуле `math` есть такая функция. Давайте импортируем её в нашу программу # In[ ]: import math math.sqrt(4) # А чтобы каждый раз не писать `math`. перед вызовом конкретных фукнций можно поступить так: # In[ ]: from math import sin sin(3.14) # Ну хорошо, что мы всё приближенно, давайте точно посчитаем, чему равено $sin(\pi)$. В модуле math можно найти это самое $\pi$ # In[ ]: from math import pi sin(pi) # Возникают вопросы: # * ЭТО ВООБЩЕ ЧИСЛО? # * почему так получилось? # ### Переменные # В Python не надо как-то спецально объявлять переменную. Присвоил значение и поехали! # In[ ]: x = 4 x # In[ ]: # Инкрементация x = x + 2 x+=2 # тоже самое x # In[ ]: # Логические операции # In[ ]: x != 7 # In[ ]: x > 7 # In[ ]: x < 10 # ### Задание # # *Числа Фибоначчи* или *последовательность Фибоначчи* — последовательность чисел, начинающаяся с двух единиц, и такая, что очередное число в этой последовательности равно сумме двух предыдущих. Формально можно определить её следующим образом: # # $a_1=1$; # # $a_2=1$; # # $a_{n+1}=a_n+a_{n-1}$ для всех $n>2$. # # Например, $a_3=1+1=2$, $a_4=2+1=3$. # # **Задача:** посчитать 15-е число Фибоначчи # In[ ]: a = 1 # первое число b = 1 # второе число i = 2 # номер того числа, которое находится в переменной b (сейчас это a_2) # In[ ]: c = a + b #нашли следующее число i = i + 1 #увеличили i на 1 a = b b = c # или можно сделать в одну строчку # a,b = b,c print i, b # команда print выводит на экран значение переменных # и всякие другие штуки # Питон выполняет команды последовательно, строчку за строчкой, поэтому порядок следоавния команд очень важен. Выполняя эту ячейку несколько раз, вы будете получать каждый раз очередное число Фибоначчи. # ### Типы данных # До сих пор мы имели дело только с числами, но уже поняли, что вещественные числа отличаются от целых. Вообще в Python есть много разных типов данных, предназначенных для хранения информации разной природы. Каждый тип данных имеет название в Python, например, целые числа — это `int`, вещественные (числа с плавающей запятой или правильнее сказать плавающей точкой) — `float`. # # #### Строки # Строки выглядят так: # In[ ]: print 'Hello, World!' # Вот эта штука в кавычках — это и есть строка (тип данных `str`). Строки тоже можно сохранять в переменных и делать с ними разные операции (но совсем не такие, как с числами). # In[ ]: type('Blah-Blah') # In[ ]: a = "Hello" b = "World" print a + b # In[ ]: # Форматирование строк x = 123 # Хочу: # x is equal to 123 print 'x is equal to %i' % x # Здесь символ процента означает, что нужно взять переменную, которая написана справа, и подставить в строчку, написанную слева, вместо символов `%i`. Буква `i` здесь означает `integer`, то есть что ожидается целое число. # In[ ]: 'ABC' == 'abc' # In[ ]: 'ABC' < 'DEF' # #### Списки # До сих пор мы работали с числовыми переменными — в каждой переменной лежало одно число. На практике нам зачастую приходится работать с большими массивами данных. Чтобы их хранить, нужно познакомиться со *списками*. Список — это такая переменная, которая содержит в себе сразу много элементов. # In[ ]: x = [2, 5, 1, 2, 3, 2, 4, 6] # вот эта штука в квадратных скобках — это и есть список # Можно обращаться к отдельным элементам списка и работать с ними как с обычными переменными. Чтобы выбрать элемент, нужно указать его номер. # # > **Нумерация начинается с нуля!** По старой программистская традиции, чтобы запутать непосвященных. # In[ ]: x[0] # In[ ]: x[1] = 10 x # Список можно расширять! # In[ ]: x.append(2) x # In[ ]: type(x) # Слово `append` — это метод класса `list`. У `x`, как у любого списка, есть много методов. Можно набрать `x.`, нажать табуляцию, и получить список доступных методов. Например: # In[ ]: x.count(2) # считаем количество "2" # In[ ]: x.reverse() # пустые скобки означают, что мы вызываем функцию, # но параметров ей не передаем x # In[ ]: # Cписок можно попробовать отсортировать x.sort(reverse=True) print x # #### Слайсы # Иногда нам нужен не весь список, а его кусочек. # In[ ]: print x print x[2:5] print x[2:] print x[:5] # #### Присвоение и копирование списков # Списки могут быть коварными. # In[ ]: y = x y[0] = 15 # Что же лежит в первом элементе списка x? # 10 ил 15? x # **ШТАА?!** Когда мы изменили список `y`, то изменился и список `x`! Почему так произошло? Дело в том, что списки живут в своём собственном мире платоновских идей. # # Когда мы присваиваем список переменной, то есть пишем что-нибудь вроде # x = [1, 2, 3] # # мы говорим, что теперь переменная `x` будет указывать на этот список. Можно сказать, что мы создали список и дали ему *имя* `x`. После этого в `x` хранится не сам список, а указатель (ссылка) на него. Когда мы присваиваем значение `x` новой переменной `y`, мы не производим копирование списка, мы копируем только указатель. То есть `y` просто стала другим именем для того же самого списка, что и `y`. Поэтому изменение элементов `x` приведет к изменению `y`, и наоборот. # # Если мы хотим создать новый список, скопировав существующий, нужно использовать вот такой синтаксис: # In[ ]: y = x[:] y[1] = 10 print x print y # ### Преобразование типов # In[ ]: a = 10.8 b = int(a) print b # In[ ]: a = '213' x = a + a print int(x) # ### Картинки # Немного картинок, чтобы было повеселее. # Для рисования графиков в основном используют модуль matplotlib. Однако, он далеко не единственный, и кроме того, далеко не самый "изящный". Посмотрите, например, [seaborn](http://stanford.edu/~mwaskom/software/seaborn/)! # In[ ]: import matplotlib.pyplot as plt import numpy as np get_ipython().run_line_magic('matplotlib', 'inline') # In[ ]: plt.plot([1,2,3,4],[4,2,3,1]) # In[ ]: plt.bar([1,2,3,4,6],[1,2,3,4,10]) # In[ ]: x = np.arange(-10, 10, 0.5) y = x**2 plt.plot(x, y) # В "сыром" виде выглядит не так чтобы очень. Но всегда можно заморочиться. И себе приятно, и семенаристу (который будет смотреть твои домашнки)! # In[ ]: # Особый стриль графиков plt.style.use('ggplot') # Это надо, чтобы писать русскими буквами font = {'family': 'Verdana', 'weight': 'normal'} plt.rc('font', **font) # In[ ]: x = np.arange(0, 6*np.pi, 0.3) y = np.sin(x) z = np.cos(x) plt.figure(figsize=(8, 6)) plt.plot(x, y) plt.plot(x, z, 'b') plt.xlabel('x') plt.title(u'Тригонометрия!') plt.legend(['sin', 'cos']) # ### Веселье закончилось. Идем дальше. # ### Условные операторы # Часто в программе возникают "развилки" - когда в зависимости от выполнения какого-то условия, программа должна пойти по тому или иному пути. # # В Python, как и во многих языках программирования, такие развилки задаются словом `if`: # In[ ]: x = 3 if x == 2: print 'Okay' print 'This is good number' else: print 'Oh, noooo!' if x > 2: print 'x is greater than 2' else: print 'x is lesser than 2' # Можно задавать несколько условий, объединяя их логическими операторами **И**,**ИЛИ** **НЕ** # In[ ]: x = 1.5 if x > 2 and x < 3: print 'Okay' # In[ ]: if x < 2 or x < 3: print 'Okay' # In[ ]: if 1 < x < 5: print 'Ok' # ### Цикл `for` # Часто нужно сделать какое-то действие со всеми элементами списка. Для этого есть цикл `for`. # In[ ]: x = [1, 4, 9, 1] i = 1234 for i in x: print i print "One more" # print i + 1 print "And finally" print i # #### `break` и `continue` # Говоря о циклах, нужно упомянуть два специальных способа прекратить обработку очередного элемента. Ключевое слово `continue` означает, что нужно вернуться в начало цикла и взять следующй элемент. # In[ ]: for i in xrange(1, 10): if i**2>10: print 'Next' continue else: print i print 'Ok' # In[ ]: for i in xrange(1,10): if i**2>50: print "Stop" break else: print i print "Okay" print "Stopped" # ### Цикл `while` # Иногда нужно выполнять какие-то команды до тех пор, пока *что-то не произойдёт*. Например, мы выводим на экран числа Фибоначчи, но только те из них, которые меньше 1000. Это делается с помощью цикла `while`. # In[ ]: a = 1 b = 1 while b < 1000: c = a + b a = b b = c print a # Если условие не выполняется до входа в цикл, то тело цикла не выполнится ни разу. Если вы хотите цикл с постусловием (то есть условием, проверяющимся в конце), то мне придётся вас расстроить: в Python его нет. Есть только вот такая конструкция, его заменяющая. # In[ ]: x=10 while True: print "Hello" x=x+2 if not (x<5): break # ### Простые задачки # **Задача 1.** Ввести числа `a`, `d` и `N`. Найти сумму первых `N` членов арифметической прогрессии с первым членом `a` и разностью `d`, не пользуясь «школьной» формулой. # # **Задача 2.** Ввести число `N` с клавиатуры. Найти сумму первых `N` членов гармонического ряда. # # **Задача 3.** Ввести натуральное число `N` с клавиатуры. Проверить, является ли оно простым. # # **Задача 4.** Вывести `N` первых простых чисел. # # **Задача 5.** Даны три числа: `a`, `b`, `c`. Не пользуясь функциями `min`, `max` и какими-либо библиотечными функциями, вывести на экран максимальное из них. # ### Продолжаем любить Питон # #### Пользовательские функции. Примочки функциональных языков # In[ ]: func = lambda x: x**2 # In[ ]: # Это тоже самое, что и сверху def func(x): return x**2 # In[ ]: func(4) # In[ ]: l = range(10) l2 = map(func, l) l2 # In[ ]: reduce(lambda x, y: x+y, l) # In[ ]: filter(lambda x: x>=5, l) # In[ ]: string = 'lala. alala, dada' no_punct = filter(lambda x: x not in ['.', ','], string) no_punct # ### Работа с файлами # В общем случае, работа с файлами осуществляется через команду `open`. Давайте попробуем создать файл с каким-то текстом: # In[ ]: fout = open('temp.txt', 'w') # In[ ]: string = 'this is very interesting text\n' fout.write(string) fout.close() # Попробуем записать несколько строк: # In[ ]: string_arr = ['Indeed, this text is very interesting,\n', 'You should read it again', ' and again'] with open('temp.txt', 'w') as fout: fout.writelines(string_arr) # Теперь, загрузим содержание файла: # In[ ]: with open('temp.txt', 'r') as fin: data = fin.readlines() data = map(lambda (x): x.strip(), data) # Как правило, в зависимости от области применимости модуля Python, в нем есть свои функции загрузки из различных форматов файлов в нужный тип данных. В следующий раз мы поработаем с прекрасным модулем `Pandas`, созданный для работы с таблицами всевозможных сортов. А сейчас - посмотрим что есть в `NumPy`. # Загрузите [файл 1](https://www.dropbox.com/s/x3vkibryoaorspk/tutorial_dataset.csv?dl=0) и [файл 2](https://www.dropbox.com/s/80dei36s1gqhbu9/tutorial_dataset_2.csv?dl=0) в папку с тетрадкой. С помощью функции `loadtxt` в модуле *NumPy* загрузите табличные данные одного из файлов. Присвойте y = D[:,0] а X = D[:, 1:]. # # Оцените коэффициенты линейной регрессии $\hat{y} = X\hat{\beta}$, где # # $$ \hat{\beta} = (X^T X)^{-1} X^T y $$ # Остатки модели рассчитываются как # $$ \text{res} = y - \hat{y} $$ # # Итак, еще раз: # # 1. Загрузите данные # 2. Обучите модель # 3. Постройте два графика: # 3.1. Выберите какой-нибудь признак (кроме x0) и на одном графике изобразите зависимость y~x и линию регрессии # 3.2. Постройте график остатки~y # In[ ]: # Write your code here # # # # load data D = np.loadtxt('tutorial_dataset.csv', skiprows=1, delimiter=',')