воскресенье, 3 января 2016 г.

О работе с данными и их визуализации в python


Для анализа данных будем использовать следующие пакеты:
  • pandas - загрузка, хранение (в DataFrame), манипуляции;
  • seaborn, statsmodels - визуализация (использует matplotlib);
  • scipy.stats - некоторые статистические функции, в том числе проверка гипотез.
Прекрасный вариантом будет строить интерактивные диаграммы с помощью plotly или включать интерактивные matplot графики в Jupyter Notebook применяя mpld3, но не сегодня :)

Рабой средой будет Jupyter Notebook - удобная оболочка для Питона работающая в браузере. Она может быть практичнее IDE или классической интерактивной оболочки потому, что показывает графики в том же окне, на манер многих математических пакетов.

import pandas as pd

Загрузка данных и просмотр

Загрузим данные из CSV файла, где одно значение от другого отделяет запятая. В этом примере у данных отсутствует заголовок - первая строка файла с названиями полей. Поэтому укажем параметр header=None дабы данные в первой строки не принять за названия полей.
pdata = pd.read_csv('filename.csv', delimiter=',', header=None)
В самом начале посмотрим, что же загрузили:
pdata.info()
0     1307 non-null object
1     0 non-null float64
2     0 non-null float64
3     1306 non-null object
...
17    1500 non-null int64
Итак, загружено 1500 записей (строк файла), 18 полей. В первом поле 1307 записей имеют значения, во втором не одного, и так далее. Определены типы данных в некоторых полях.
Посмотрим более детальную информацию по каждому из полей:
pdata.describe()
1   2   4   7            8   11    13            15               16  \
count   0   0   0   0  1500.000000   0  1500   1497.000000      1497.00
mean  NaN NaN NaN NaN     1.852667 NaN     2  52300.977288   2967182.03
std   NaN NaN NaN NaN     0.837911 NaN     0  19574.930119   1710899.18
min   NaN NaN NaN NaN     1.000000 NaN     2     33.000000      2500.00
25%   NaN NaN NaN NaN     1.000000 NaN     2  46400.000000   1850000.00
50%   NaN NaN NaN NaN     2.000000 NaN     2  55000.000000   2950000.00
75%   NaN NaN NaN NaN     2.000000 NaN     2  62500.000000   3480000.00
max   NaN NaN NaN NaN     4.000000 NaN     2  93650.000000  10500000.00

                17 
count  1500.000000 
mean     10.500000 
std       5.768204 
min       1.000000 
25%       5.750000 
50%      10.500000 
75%      15.250000 
max      20.000000
Первой строкой приведены номера полей. Для некоторых из них вычислены среднее (mean), стандартное отклонение (std), максимальное и минимальные значения, перцентили.
Чтобы табличка выглядела красивее установим количество выводимых цифр для вещественных чисел:
pd.set_option('precision',3)
Посмотреть часть данных:
    # печатаем данные полностью
    pdata
    # ... или только голову (по умолчанию n = 5 строк)
    pdata.head()
    # ... или хвост (по умолчанию n = 5 строк)
    pdata.tail() 
 
Доступ к отдельным полям осуществляется по их названиям, которые содержатся в списке columns:
pdata.columns
Если там ничего нет, то добавим. Предпологаем, что у нас только два поля, ибо число заголовков должно соответствовать числу полей:
pdata.columns = ['price', 'price_m2']
Затем, обратимся к полю price чтобы просмотреть значения:
pdata['price']
или так
pdata.price
Если известен только номер нужного поля, например 10:
pdata1[pdata.columns[10]]
Одновременно можно выбрать несколько полей, например для создания нового объекта DataFrame
df2 = df[df.columns[ [-12,-8,-6,-4,-3,-2] ]] 
А может быть нас интересует конкретный элемент, например в первой записи 10-го поля:
pdata1.iloc[1,10]

DataFrame поддерживает и сложные запросы, например можно указать несколько условий для разных столбцов. Кроме того можно применять функции к отдельным столбцам. Подробнее: https://habr.com/company/ods/blog/322626/

Алсо

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

Создание объекта DataFrame из списков

Вместо получения данных из файла, объединим два списка в объекте DataFrame.
price =  [4.65, 2.3, 5.8, 1.35, 4.8, 7.5, 3.3, 2.95, 2.95, 1.8, 1.6, 3.399, 5.9, 3.0, 1.6, 3.3, 1.85,
2.033, 2.23, 1.854, 3.48, 3.5, 2.75, 2.35, 2.95, 3.2, 2.75, 1.55, 2.1, 2.8, 2.8, 1.37, 2.1, 6.2,
3.65, 3.1, 3.35, 3.3, 3.85, 2.2, 2.85, 4.5, 3.3, 1.18, 3.79, 3.25, 3.18, 1.59, 1.3, 2.45, 2.2, 
2.563, 2.1, 1.25, 3.2, 2.1, 3.69, 2.86, 2.37, 3.5, 2.06, 4.3, 4.55, 5.1, 1.9, 2.1, 2.65, 10.5,
2.24, 1.77, 1.35, 2.2]
price_m2 = [58.86, 38.333, 71.604, 40.909, 58.536, 62.5, 55.0, 56.73, 49.166, 64.285, 31.372,
48.557, 93.65, 75.0, 53.333, 68.75, 57.812, 49.585, 53.095, 46.35,  46.4, 67.307, 45.081, 55.952,
60.204, 53.333, 78.571, 43.055, 37.5, 66.666, 41.176, 29.782, 51.219, 87.323, 52.142, 50.0, 67.0,
55.0, 71.296, 42.307, 41.304, 57.692, 47.142, 28.78, 57.424, 50.781, 46.086, 49.687, 40.625, 61.25,
43.137, 51.26, 47.727, 50.0, 61.538, 47.727, 47.307, 42.058, 47.4, 53.846, 46.818, 57.333, 56.875,
43.589, 5.882, 61.764, 41.406, 55.851, 48.695, 42.142, 28.723, 53.658]
# создадим DataFrame из 2-х списков сразу указав соответствующие спискам имена полей. 
# Пусть в этом примере имена списков и имена полей совпадают:  
df = pd.DataFrame({'price': price, 'price_m2': price_m2})

Обработка данных

Далее, стоит привести данные к пригодному для обработки виду.
Удалить одинаковые записи, если в этом есть необходимость:
pdata1 = pdata.drop_duplicates()
Положив именованный параметр inplace функции drop_duplicates равным True избавляемся от создания нового объекта, как это происходило выше. Теперь можно записать так
pdata.drop_duplicates(inplace=True)
pdata теперь не содержит дубликатов.
Многие функции имеют подобный параметр, что даёт возможность избавиться от лишнего копирования.

Сохраним данные в файл
pdata.to_csv('data.csv') 
Алсо
Конвертировать текстовое представление даты в дату (объект datetime)
Предположим, что поле time состоит из записей вида 2016.08.06 18:15.
Data.time = pd.to_datetime(Data.time)
Если необходимо, вторым параметром метода to_datetime устанавливается формат даты в исходной строке. Для вышеприведйнной строки формат должен быть описан следующим образом: %Y.%m.%d %H:%M

Графическое представление данных

Чтобы нарисовать красивые графики и диаграммы используем пакет seaborn. Это не единственный способ создавать различные диаграммы и графики (matplotlib), но, наверное, самый красивый.
import seaborn
# для показа сгенерированных картинок используем matplotlib
import matplotlib.pyplot as plt
Далее будем использовать plt без отдельного импорта пакета и иногда будем опускать код, добавляющий необходимые пояснения к представленным на рисунках данным:
# установим заголовок для графика
plt.title("Диаграмма рассеивания: цена квартиры - цена $м^2$"); 
# подпишем оси координат обозначив единицы измерения
plt.xlabel("Цена $м^2$, тыс.руб.")
plt.ylabel("Цена квартиры, млн.руб.")
Если в качестве рабочей среды используется ipython notebook (теперь Jupyter Notebook), то нужно включить интеграцию с matplotlib (графики в том же окне) [so]:
%matplotlib notebook
При необходимости можно установить размер и разрешение графиков:
figure(figsize = (80,40), dpi=100)  # размеры в дюймах
# установить размер шрифтов на графиках
matplotlib.rcParams.update({'font.size': 16})
***
Самый быстрый способ что-нибудь нарисовать - использовать метод plot
df.plot(x='price', y='price_m2', kind='scatter')  # построим диаграмму рассеивания
 параметр kind может принимать значения: 'line', 'bar', 'barh', 'kde', 'density', 'scatter'.
Отображает данные на плоскости или в пространстве. Значения случайных величин откладываются вдоль осей координат. В примере каждая запись из DataFrame представлена точкой с координатами price и price_m2.
seaborn.regplot(x='price_m2', y='price', data=df); plt.show()
В качестве первых двух параметров передаются названия полей (df.columns) DataFrame. Линия тренда отключается параметром fit_reg=False.
Ещё один вид представления диаграммы рассеивания
# нарисуем ещё и линию тренда kind='reg'
seaborn.jointplot(x='price_m2', y='price', data=df, kind='reg');
# подпишем оси координат
plt.xlabel("Цена $м^2$, тыс.руб.");
plt.ylabel("Цена квартиры, млн.руб");
plt.show();
 

Здесь в дополнение к непосредственно данным приведён линейный коэффициент корреляции (Пирсона) - pearsonr и  p-уровень значимости.
Ибо p-value меньше уровня значимости 1% (0.00013 < 0.01) гипотеза о статистической взаимосвязи между величинами может считается верной.

Отмечу, что у меня получилось корректно подписать оси координат для графика в центре только после того как был добавлен параметр стиля в функцию jointplot. Фактически на картинке 3 графика и необходимо  указывать какому из графиков предназначаются подпись для осей координат.

Гистограмма и кривая плотности распределения
import seaborn
from matplotlib.pyplot import show  # чтобы смотреть картинки без сохранения
seaborn.distplot(price)  # подготовим гистограмму и кривую распределения
show()  # покажем картинку

При необходимости можно настроить представление добавив параметры в функцию distplot:
fit=norm - нарисовать поверх данных кривую нормального распределения;
label = 'имя' - указать имя для гистограммы и кривой, чтобы не спутать их с другими;
color = 'y' - изменить цвет;
kde = False - не рисовать kernel density estimate (ядерную (?) оценку плотности вероятности), это кривая на графике выше;
hist = False - не рисовать гистограмму.

Boxplot (ящик с усами или диаграмма размаха)
График показывает сразу несколько параметров распределения:
медиану - линия внутри ящика;
стенками ящика (квартили 0.25 и 0.75) ограничены 50% выборки;
Длинна усов рассчитывается по-разомну.
Это может быть просто минимальное и максимальное значения в выборке. Второй вариант - полторы ширины ящика (расстояния между квартилями 0.25 и 0.75). Тогда точками отмечаются выбросы.
seaborn.plt.title("Диаграмма размаха цен за $м^2$")  # Дополним график заголовком
ax=seaborn.boxplot(price_m2) 
ax.set(xlabel='цена за $м^2$, тыс.руб.')  # добавим подпись к оси абсцисс
plt.show()

Несколько диаграмм на одном рисунке doc

# расположим графики по 2 в столбце в 1 столбец
# и пусть графики имеют общую ось Х
f, ax = plt.subplots(2,1, sharex=True)
подпишем каждый график
ax[0].set_title("Гистограмма распределения")
ax[1].set_title('Диаграмма рассеивания')
# а также ось абсцисс. 
# она будет расположена в низу нижнего графика, поэтому добавим подпись только туда
ax[1].set_xlabel('тыс.руб.')
# явно укажем в параметре ax в каком месте какой график изображать
seaborn.boxplot(price, ax=ax[1])
seaborn.distplot(price, ax=ax[0])
# озаглавим всю картинку, а чтобы текст не сливался с остальными подписями сделаем его шрифтом покрупнее
plt.suptitle("Характеристики распределения цен за $м^2$", size=16)
plt.show()

 

 

Пример

from math import *
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm  # для построения qq plot
from scipy.stats import norm, normaltest
import seaborn
 
file = "apartments.csv"
 
# загружаем данные из CSV файла.
# данные представлены списком строк, значения в которых разделены одно от другого зяпятой ","
pdata_ = pd.read_csv(file, delimiter=",")
 
# В файле содержится много лишней информации, удаляем некоторые поля(столбцы) axis=1 указав их номера как в списке
pdata = pdata_.drop(pdata_.columns[[0,1,2,3,4,5,7,9,11,13, -1]], axis=1)
 
# устанавливаем заголовки для полей, в дальнешем их можно использовать как атрибуты
pdata.columns = ['name', 'rooms', 'addr', 'square', 'floor', 'price_m2', 'price']
 
print("Загружено %i записей"%len(pdata))
 
# удалим дубликаты, изменения зразу "запишем" в тот же объект
pdata.drop_duplicates(inplace=True)
 
# После загрузки, числовые значения для некоторых числовых полей имеют тип string
# конвертируем значения этих полей в числа. неконвертируемые значения станут NaN
pdata.price_m2.convert_objects(convert_numeric=True, copy=False)
pdata.price.convert_objects(convert_numeric=True, copy=False)
 
# Удалим все записи (строки) целиком если они содержут Na или NaN хотя бы в одном поле
pdata.dropna(inplace=True)
# или
# заполним недостающие значения для одного поля
pdata.price.fillna(52, inplace=True)
# или для всех полей
pdata.fillna(123, inplace=True)
 
# удалим ещё и записи, где значение поля price_m2 меньше 1000
pdata = pdata[ pdata.price_m2 > 1000 ]
 
# поделим все значения в полях на ...
pdata.price_m2 = pdata.price_m2.map(lambda x: x/1000)
pdata.price = pdata.price.map(lambda x: x/1000000)
 
print("Всего уникальных записей: %i"%len(pdata))
print("Уникальных записей по полям")
# цикл по парам (имя_поля, Series - содежание поля)
# напечатать число уникальных значений для каждого поля
for colname,rows in pdata.iteritems():
    print("{0: <9}: {1}".format(colname, len(pd.unique(rows))))
 
seaborn.plt.title('Диаграмма рассеивания: цена $м^2$ - цена квартиры')
ax = seaborn.regplot(x='price_m2', y='price', data=pdata)
ax.set(xlabel='Цена $м^2$, тыс.руб.', ylabel='Цена, млн.руб.')
plt.show()
 
print("\nРаспределение цен кв. метра квартиры, руб")
print("Среднее: {0}".format(pdata.price_m2.mean()))
print("Медиана: {0}".format(pdata.price_m2.median()))
print("Ср. кв. отклонение: {0}".format(sqrt(pdata.price_m2.var())))
print("Мода(моды):\n{0}".format(pdata.price_m2.mode()))
 
seaborn.plt.title('Плотность распределения цен')
seaborn.distplot(pdata.price, axlabel='Цена, млн.руб.')
plt.show()
 
seaborn.plt.title('Плотность распределения цен за $м^2$')
seaborn.distplot(pdata.price_m2, axlabel='Цена $м^2$, тыс.руб.')
plt.show()
 
sm.qqplot(pdata.price_m2, line='s')
plt.title('Гипотеза о нормальности распределения цен за $м^2$')
t = normaltest(pdata.price_m2)
print("\nПроверка гипотезы о нормальности распределения цен за кв.м. квартиры")
 
if t[1] < 0.05: print("Распределение НЕ является нормальным (p-value = %0.3f > 0.05)"%t[1])
else: print("Цены распределеные нормально (p-value = %0.3f < 0.05)"%t[1])
plt.show()

После того, как данные представленны графически, проверим несколько статистических гипотез.

Проверка гипотезы о равенстве средних.
Предположим, что имеется две выборки. Например массы кошек и котов. Если вычислить средние массы самцов и самок наверняка получатся отличающиеся цифры. Даже если массы самцов и самок у данного вида животных не отличаются. Но прежде чем мы это выясним нужно ответить на вопрос. Какие различия между средними массами выборок считать значимыми, а какие нет, т.е. получившимися в силу случайности измеряемой величины.

Чтобы ответить на этот вопрос во-первых нужно учитывать, обёмы выборок. Что если выборки маленькие, и совершенно случаной в выборку самцов попали только коты-толстяки, а в выборку самок кошки без лишнего веса?)
Конечно чем больше выборка, тем меньше вероятность что туда попадут исключительно коты с нетипичной массой.
Во-вторых нужно учитывать на сколько вообще случайна масса самих кошек и котов. Если мы будем помещать в выборку кошек разной породы, то там будут самые разные массы. Стало быть если разброс масс может быть большой, то можно думать, что и средние тоже могут отличатся сильнее.

Поэтому чтобы сделать обоснованый вывод о равенстве средних нужно учесть характеричтики выборок. Для этого существуют специальные процедуры сравнения. Они называются статистическими критериями (тестами). Некоторые из них.
Одни критерии применимы для маленьких выборок, порядка единиц. Другие можно применять только для больших выборок, а третьи только для выборок распределённых по нормальному закону.

Помимо этого, одни критерии (или их варианты) применимы для зависимых, а другие для независимых выборок.
Зависимые выборки - это те где одному объекту из первой выборки соответствует обхект из второй. Стало быть выборки должны иметь один и тот же объём.
Например близнецов можно рахбить на две выборки. У каждого близнеца будет ровно один брат (или сетра) в другой выборке. Причём не любой брат, а именно его брат.
Другой пример зависимых выборок - рост людей в 20 и в 30 лет. Здесь человеку ставится в соответствие он же сам.

Для независимых выборок нельзя сказать, что именно этому объекту из первой ыборки соответствует именно из второй. Пример с кошками как раз представляет собой две независимые выборки.

Проверим гипотезу о равенстве средних используя t-критерий Стьюдента. (Притворимся что выборки имеют нормальное распределение).
Нулевая гипотеза здесь (как и во многих похожих тестах) следующая: математические ожидания равны. Если точнее, то равны именно математические ожидания генеральныз совокупностей из которых сделаны выборки. Ведь выборочные мат.ожидания мы и без критериев сравнить можем.

from scipy.stats import *

y = [16.8, 18, 20.3, 17.3, 18.9, 18]
x = [18.5, 17.5, 18.5, 19.8, 17.9, 19.4] 
 
ttest_ind(x, y)
 
# Результат
Ttest_indResult(statistic=0.61784218471924157, pvalue=0.55048986906612796)
 
В результате нам интересно p-value. Оно здесь заметно больше всякого разумного уровня значимости (например 0.05) поэтому оснований для отклонения нулевой гипотезы нет: матожидания генеральных совокупностей равны.

Другие статистические критерии для проверки равенства средних:
ttest_rel(x,y) - t-критерий для зависимых выборок.
ttest_ind(x,y) - t-критерий для независимых выборок.
wilcoxon(x,y) - критерий Уилкоксона (зависимые выборки) 
mannwhitneyu(x, y, ...) - U-критерий Манна — Уитни (независимые выборки)
 






Вычисление коэффициента корреляции Пирсона и проверка его значимости.
Коэффициент корреляции Пирсона (лиейный коэффициент корреляции) описывает силу линейной зависимости между двумя случайными величинами. Он принимает значения в отрезке от 1 до -1. Значение к.к. Пирсона близкое к нулю говорит об отсутствии (слабой зависимости) линейной зависимости между случайными величинами. Значение близкое по модулю к еденице, наоборот говорит о сильной линейной зависимости. Стоит отметить, что случайные величины могут быть связаны ещё и нелинейной зависимостью, тогда к.к. Пирсона здесь плохой помошник. Кроме того, вычисляя к.к. по выборке можно совершенно случайно получить то или иное значение к.к., поэтому имеет смысл оперировать ещё и степенью уверенности для этого значения. В математической статистике для этого служит p-value - вероятность получить такое или ещё более выраженное значение случайно. На практике, особенно при небольших объемах выборки нулевого p-value добится не получается, поэтому довольствуются некоторыми малыми вероятностями того, что величниа (в нашем случае к.к) получена не случайно. Обычно, в соответствии с принципом практической невозможности маловероятных событий, принимают допустимую вероятность ошибки в 0.05 или 0.01. Однако стоит обратить внимание на то, что при многократном извлечении выборки и вычислении параметра, можно получить желаемое значение параметра совершенно случайно.
from scipy.stats import perasonr
# функция возвращает к.к. Пирсона и p-value 
# проверяется гипотеза о том, что такое значение к.к. Пирсона получено случайно
r,p = pearsonr(price_m2, price)
>>>(0.48992003383028732, 1.2541938539342937e-05)
В итоге имем значение к.к. r= 0.49
p-vlue = 0.000013 < 0.01, значение гораздо меньше допустимой вероятность ошибки - отвергаем гипотезу о случайности данного значения к.к.Пирсона. Этому значению r можно доверять.

***

Генерирование значений случайной величины


Модуль scipy.stats содержит множество классов, каждый из которых предназначен для работы с определённым распределением.

Несколько примеров:
scipy.stats.uniforn - равномерное распределение
scipy.stats.norm - нормальное распределение
scipy.stats.t - распределение Стьюдента (t-распределение)
scipy.stats.poisson - распределение Пуассона

Эти классы имеют схожие методы для генерирования случайных значений - rvs.

Генерирование одного значения СВ распределённой по стандартному нормальному закону:
scipy.stats.norm.rvs()

Различия в вызове функции rvs для каждого подмодуля - это различия в параметрах распределений.
Например равномерное распределение (uniform) имеет два параметра определяющие минимальное и максимальное значение СВ.
Нормальное распределение имеет тоже два параметра, но это математическое ожидание и стандартное отклонение.

Параметры функции rvs
функция rvs имеет три параметра которые и задают параметры распределения эти параметры loc, shape, scale
какие из этих трёх параметров нужно задавать и какой смысл они имеют напиcано в документации к подмодулю

параметры указываются так:
scipy.stats.norm.rvs(loc = 12.2)
Для параметра shape приводится просто число:
scipy.stats.norm.rvs(5.72)

Пример

help( scipy.stats.norm )
The location (loc) keyword specifies the mean.
The scale (scale) keyword specifies the standard deviation.
loc - это математическое ожидание
sсale - стандартное отклонение

Отдельным параметром size задаётся количество значений СВ которые нужно сгенерировать.

Создание 100 значений нормально распределённой случайной величины с математическим лжиданием 4 и стандартным отклонением 7.

scipy.stats.norm.rvs(loc=4, scale=7, size=1000)


Друге примеры в jupyter блокноте: https://github.com/VetrovSV/ST/blob/master/Python.%20Statistics.ipynb

 

Вычислить значение функции распределения - CDF
CDF (cumulative distribution function) - функция распределения случайной величины. Значение этой функции - вероятность в которой случайная величина X примет значение меньше заданного x:
F(x) = P(X < x)
Графически это площадь под кривой плотности вероятности (PDF), например такой

На рисунке, вероятность того что случайная величина примет значении меньше 1 закрашена серым. Площадь под любой кривой распределения всегда равна еденице.

При проверке статистических гипотез или вычислении доверительных интервалов нужно вычислять значение функции распределения случайно величины. В каждом конкретной задаче случайная величина может быть распределена по какому угодно закону т.е. иметь свою форму кривой плотности вероятности. 

Кроме проверки гипотез, CDF может пригодится и для вычисления вероятности того, что случайная величина примет значение лежащие в отрезке. Такая вероятность вычисляется по формуле:
P(x1 < X < x2) = F(x2) - F(x1)
Формулу легко представить как разность двух площадей.
В пакете scipy функции распределения имеют схожий интерфейс, у каждой можно вызвать cdf, pdf, isf функции. Приведём пакеты некоторых функции распределения из них.
CDF для стандартного (нормированого) нормального закона и других законов

    from sicpy.stats import norm # нормальное распределение
    norm.cdf(3)
    0.9986501019683699

Это же значение можно подсмотреть и в таблице pdf

from scipy.stats import f  # распределение Фишера
from scipy.stats import t  # распределение Стьюдента (t распределение)
from scipy.stats import chi2  # распределение Хи-квадрат
from scipy.stats import poisson  # распределение Пуассона


Если обозначить площадль слева от заданной ординаты как p (закрашени область на рис. выше), то площадь справа q = 1 - p.
Получить ординату точки по значению q  работа функции isf.

Приведём несколько примеров:

p = 0.95
q = 1 - p
norm.isf(q)
>>> 1.6448536269514722
norm.cdf(_)  # проверим результат
0.94999999999999996


# для некоторых распределений необходимо указывать их параметры, здесь - число степеней свободы
t.isf(0.05, df=100)
>>> 1.6602343260657506
 # t.cdf(_, df=100)  проверим результат
>>> 0.94999999999802531


Алсо

R - язык программирования созданным специально для обработки данных. R Studio - среда разработки.

Ссылки

воскресенье, 30 августа 2015 г.

linux notes

www.zabrosov.ru - обширная шпаргалка по командам Линукс в примерах.
Некоторая часть из нижеописанного актуальна для ubuntu и подобных дистрибутивов.

*** Как загрузить Ubuntu без графики? [from]
В меню загрузки ОС отредактировать конфигурация заменив quiet splash на text.

*** Как избежать сохранения команды в истории bash?
Для этого нудно оставить перед ней пробел.

*** Как сохранить введённую в консоли команду без её выполнения? [se]
Ctrl + U - для запоминания
Ctrl + Y - для вставки запомненной команды

*** Если файл существует, то выполнить действие...
if [ -f filename ]; then echo "exists"; fi
Синтексис управляющих операторов [подробнее]


Цсловный оперетор
if условие; then ... else ... fi
if условие; then ... elif [ .. ] ... fi

Цикл с предусловием
while условие; do ... done


Условие может выглядеть так [подробнее]
(( `hcitool scan | wc -l` > 1 ))

diff etc
сравнивает содержимое файлов
раскрасить вывод diff [SO]:
diff old new | colordiff
Графические приложения для сравнения файлов: Kompare, Meld.
Последнее умеет делать слияние файлов.

Vim, [Vim Викиучебник]

Управление
i - перейти в режим (вставки) редактирования;
Esc - перейти в нормальный режим (режим ввода комманд)
v - пеерейти в режим выделения текста.
/ слово - поиск вперёд
? слово - поиск назад
n и N - следующее и предыдущее вхождение

yy - копировать строку
pp - вставить строку

:q - выход
:q! - выход без сохранения
:wq - сохранить и выйти
:set nu - включить номера строк
.vimrc - файл настроек.
...

***
wc <file>    - посчитать число строк, слов и размер файла в байтах


***

Напечатать DOC файл в консоли
antiword file

PDF

Показать PDF в консоли ][
sudo apt-get install fbi
Для просмотра пользователь должен быть добавлен в группу video:
$ sudo usermod -a -G video user
Теперь можно смотреть:
$ fbgs file.pdf
 
Собрать PDF из отдельных изображений(страниц) [SO]
convert page*.png mydoc.pdf
Вырезать из PDF файла страницы [askubuntu]
pdftk full-pdf.pdf cat 12-15 output outfile_p12-15.pdf


== latex ==
TeX-live        - core
Kile            - editor
TexMaker         - editor
texlive-latex-extra   

xneur        - PuntoSwitcher for linux
Stardict     - Context dictioary
          copy dictionaries to /usr/share/stardict/dic


***
Напечатать время в каждой строке вывода [SO]
nc localhost 30003 | awk '{print strftime("%m-%d %H:%M:%S"), $0; fflush();'
Здесь для печати времени в формате %m-%d %H:%M:%S перед каждой строкой $0 вывода nc используется скриптовый язык AWK [rus-linux, linuxgeeks].

Ещё один способ (необходим пакет moreutils)[stackexchange]
echo "foo" | ts '[%Y-%m-%d %H:%M:%S]
***
Разбить строку на поля по разделителю ':' и вывести только второе (-f 2) поле
echo email:password | cut -d ':' -f 2
***
Направить вывод команды одновременно на экран и в файл [SO, Tee]

nc localhost 30003 | tee logfile.txt


***
Сгенерировать QR-код.
qrencode "hello" -o image.png
Сгенерировать  QR-код в ASCII-арт и тут же его показать.
qrencode "hello" -t ASCII - | cat

Сеть и интернет

SSH


У каждой машины с установленным SSH сервером есть свой уникальный идентификатор - отпечаток ключа шифрования, который генерируется во вреся установки сервера. При подключении, до того как сервер запросит пароль, этот отпечаток выводится на экран. Это необходимо, чтобы удостоверится в подлинности сервера и защитить себя от MitM.

-ssh -o VisualHostKey=yes pi@192.168.2.35












Поэтому для начала нужно узнать один или несколько различных отпечатков используя программу ssh-keygen. Программе передаются два параметра -l (вывести отпечаток ключа) и -f <путь к ключу>. "Нарисовать" как и раньше отпечаток поможет ключ -v. Устаревшее шифрование алгоритмом DSA используется редко. В основном в ходу RSA и ECDSA.
Узнать отпечаток ECDSA ключа
ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key
Отпечатки могут быть по разному представлены (в зависимости от версии SSH [SU]), например клиентская программа напечатает в виде шестнадцатеричного числа, а сервер (комманда ssh-keygen) в base64.

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

Сгенерируем ключи
ssh-keygen
они будут сохранены в .ssh/id_rsa, откуда  потом их можно загрузить в память:
ssh-add key_file
Просмотреть загруженные ключи
ssh-add -l
***
Копировать файл по ssh на удалённый хост
scp file user@host:new_file

Посмотреть отпечаток ключа сервера
ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub
***
Отпечаток публичного ключа ssh-сервера (например ECDSA key fingerprint is 09:0c:2f:bb:9d:f3:69:21:5c:3c:a9:ec:dd:a2:18:16) трудно запомнить, однако его можно "рисовать" при подключении подобным образом [www.howtogeek.com]:

с помощью опции -o VisualHostKey=yes:
ssh -o VisualHostKey=yes user@host
***
Не добавлять адрес в список известных.
Иногда при подключении к серверу нет необходимости добавлять его с список доверенных (known_hosts). Один их способов, это самостоятельно указать путь для этого файла, заменив его на /dev/null (-o UserKnownHostsFile=/dev/null):
ssh -o UserKnownHostsFile=/dev/null user@some_server

***

Смотреть файлы на удаленной машине удобнее всего через файловый менеджер. Например в nautilus: File > Connect to Server... В качестве адреса использовать: sftp://user@server. Фактически будет смонтирована удалённая файловая система. Это в частности решает проблему просмотра графических и др. файлов в консоли.

*** Socks-proxy
Чтобы дать возможность обращатся локольному приложению с IP ssh сервера к другим машинам можно настроить ssh в режиме socks-прокси. Это решит и проблему открытого или недоверенного соединения с интернетом, например в случае публичного WiFi. Весь траффик будет передаватся по защищённому каналу между ssh клиентом и сервером, и в конце концов будет исходить как буд-то от машины, на которой запущен ssh сервер.
Подключемся к серверу в режиме socks прокси
ssh -D 8080 user@server
Теперь остаётся настроть локальное приложение, например браузер, на использование прокси localhost:8080.

tmux

Менеджер терминалов, аналог screen.
tmux - запустить и создать новую сессию.
tmux attach - подключится к последней сессии. Удобно при подключении по ssh вернутся в то же место, на котором закончил в последний раз.
Запущенные в tmux приложения продолжают выполнятся, даже если соединение по ssh было разорвано.
Ctrl+b, c - создать новый терминал.
Ctrl+b, 1 - переключится на терминал #1.
Ctrl+b, d - отключится
Ctrl+b, [ - включить прокрутку
Ctrl+b " - split pane horizontally.
Ctrl+b % - split pane vertically.
Ctrl+b arrow key - switch pane.
Hold Ctrl+b, don't release it and hold one of the arrow keys - resize pane.
Ctrl+b c - (c)reate a new window.
Ctrl+b n - move to the (n)ext window.
Ctrl+b p - move to the (p)revious window.

mosh

Браузер в консоли

links2 [URL]
-dump - вывести страницу на стандартный вывод

wget 

скачать файл:
wget URL -O КУДА(имя файла)

***

Измерить пропускную способность сети - iperf
Запустить сервер, по желанию указать интерфейс -s 192.168.1.9:
iperf
Запустить клиент но 10 секунд (или на N секунд -t N):
iperf -c <server_ip>

Показать использование сети каждым процессом
nethogs

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

***
VNC
http://geckich.blogspot.com/2012/09/vino-vnc-linux.html

Подключения

Подключиться к сети my_wifi используя nmcli (network manager)
nmcli connection add con-name mynewcon ifname wlan0 type wifi ssid myssid
nmcli connection modify mynewcon 802-11-wireless-security.key-mgmt wpa-psk
nmcli connection modify mynewcon 802-11-wireless-security.psk password123

Запустить HTTP сервер в любой папке [askubuntu]
python -m SimpleHTTPServer 80
python3 -m http.server
Порт (80) можно не указывать.
Это быстрый способ сделать доступным содрежимое каталога для других.

Если требуется запустить сервер для сайта, работающего на php то:

php -S 0.0.0.0:8080



Using the NetworkManager Command Line Tool, nmcli
***

How do I change the hostname without a restart?
How to spoof the MAC address of a network interface on Linux


Отправить сообщение из консоли через XMPP

Создать простой файл конфигурации в каталоге пользователя .sendxmpprc который будет содержать имя пользователя от имени которого будет отправлено сообщение, сервер и пароль:
user@jabber.com password
Права на доступ к файлу должен имть только текуший пользователь:
chmod 0600 .snedxmpp
Наконец можно отправлять сообщение (используя tls соединение -t)
echo "Hello" | sendxmpp -t reciver@jabber.com

Отправить сообщение через публичный почтовый сервер

sendEmail -f "from@server.ru" -t "reciver@server.ru" -u "Subject" -m "message" -s "smtp.server.ru" -xu "from@server.ru" -xp password
-f адрес_отправителя
-t адрес_получателя
-u тема
-s smtp сервер[:порт]
-xu имя_пользователя_для_авторизации
-xp пароль_для авторизации

*** Узнать свой публичный IP [askubuntu]

Самый простой способ сделать это - спросить IP у одного из web-сервисов. Стоит выбирать те сайты, которые выдают IP адрес простым текстом, без лишнего оформления. Используем программу curl
curl ipinfo.io/ip
curl ifconfig.me
curl icanhazip.com
curl ipecho.net/plain; echo
Если IP адрес выдаётся в одну строку, без символа переноса строки то добавим его с помощью последующего вызова echo, как это сделано в последнем примере

Геолокация по IP

geoip <IP>
#<struct GeoIP::Country request="8.8.8.8", ip="8.8.8.8", country_code=225, country_code2="US", country_code3="USA", country_name="United States", continent_code="NA">
или
geoiplookup <IP>
GeoIP Country Edition: US, United States
GeoIP City Edition, Rev 1: US, CA, California, Mountain View, 94040, 37.384499, -122.088097, 807, 650
GeoIP ASNum Edition: AS15169 Google Inc.
How to Do IP Address Geolocation Lookups

Система

Системные мониторы (консольные)
htop
glances

*** Отправить сообщение во все открытые терминалы [stackexchange]

sudo wall -n Hello

cron

Редактировать расписание:
crontab -e
Каждая запись расписания состоит из нескольких полей [wiki]:
* * * * * выполняемая команда
- - - - -
| | | | |
| | | | ----- День недели (0 - 7) (Воскресенье =0 или =7)
| | | ------- Месяц (1 - 12)
| | --------- День (1 - 31)
| ----------- Час (0 - 23)
------------- Минута (0 - 59)
* (звёздачка) обознаяает любое значение, таким образом запись
* * * * * ~/script.py 
буде означать, что скрипт в домашнем каталоге пользователя бедет запускатся каждую минуту (каждую минуту каждого часа каждого дня месяца каждого дня недели) 
Следующая комманда будет запускатся каждые пять минут
*/5 * * * * echo "Прошло пять минут"
Вместо описания времени, можно указать событие - перезагрузка (@reboot). Тогда запись длжна выгялдеть так
@reboot ~/script.py 

Есть и другой способ запускать программу переодически. Утилита watch будет запускать скрипт script.py комманду каждый 60 секунд:
watch -n 60 ~/script.py
***
who        - who is logged?
ps        - show processes

tightvncserver  - vnc server
tightvncpasswd - set password

 

Диски и разделы

df -h             # show hdd free space
fdisk -l        # list of all disks
gparted

***
Анализ занятого места на диске из консоли [SE]
ncdu

***
gsmartcontrol                - GUI smart

== smartmontools (пакет) ==
smartctl --scan                - scan for the devices
smartctl /dev/sda -x            - show info

== fix ntfs ==
ntfsprogs                - пакет
ntfsfix /dev/sda1            - Fix common filesystem errors and force Windows to check NTFS

Сделать образ диска

dd if=/dev/sdb of=disk.img bs=4k
if - диск;
of - имя файла в который будет сохранён образ;
bs - размер блоков, которыми будет производится копирование.
По-умолчанию информации о ходе операции не показывается, чтобы это исправить нужно добавить опцию [askubuntu]
status=progress
В старых версиях во время копирования никакой информации о прогрессе не показывается.

Объём скопированных данных показывает утилита dcfldd основанная на dd. Программе можно указать дополнительные опции, которые могут быть полезны, если во время копирования возможны ошибки чтения. noerror и sync - не даст программе остановится при возникновении ошибки, а нечитаемый блок (размер указан в опции bs) при копировании будет заполнен нулями.
dd if=/dev/sdb of=disk.img bs=4k conv=noerror,sycn
Для плохо читаемых дисков иметь смысл уменьшить размер блока.
Чтобы показывать состояние [askubuntu] операции нужно добавить параметр status=progress

dd if=/dev/sdb of=disk.img bs=4k conv=noerror,sycn status=progress 


По окончанию операции копирования хорошо будет сравнить хэши:
md5sum disk.img
md5sum /dev/sdb

md5sum не показывает статуса о ходе операции, поэтому вызывая её для больших объёмов данных нельзя сказать о длительности операции. Воспользуемся отдельной программой pv, [habr] которая показывает прогресс бар, скорость и другую информацию:
pv disk.img | md5sum
Чтобы сжать образ на лету используем gzip [create a compressed backup image]:
dd if=/dev/sda | gzip -9 > /mnt/external/filename.img.gz
-1 - быстрое сжатие
-9 - качественное сжатие (медленно)

Стоит отметить, что создание образа таким способом может быть очень медленным.

=== boot manager ===
startupmanager                 - gui for grub settings

***
Температура
http://www.youisbee.ru/howto/linux/86-nastrojka-lm-sensors-v-debian-ubuntu.html

***

Установить частоту, например для четырёхрядерного процессора:
for i in 0 1 2 3; do cpufreq-set -c $i -g ondemand; done

*** music

Проиграть звук из консоли:
paplay /usr/share/sounds/KDE-Im-Sms.ogg
Воспроизвести mp3 [superuser]:
mpg123 music.mp3
cmus - консольный аудиоплеер

== other ===
bc        - console calculator
gksudo <app>    - run GUI app with root

=== console ===
Alt+.        - previous param
== screen ==
Ctrl+A, S       - split the screen horizontaly
Ctrl+A, Tab     - switch the windows
Ctrl+A, c       - create new session in a windows
Ctrl+A, |       - split the windows verticaly
Ctra+A, X       - close window

== write console to the file ==
bash > <file>     - start new session and write output to the file. (No output at the screen)
bash | tee <file> - start new session and write output to the file

== history ==
!n               - execute command with position #n in history
!-n              - execute command with position #n from tail in history
!!                - выполнить последнюю комманду

Файлы и папки

Получить полное имя файла [so]:
readlink -f file.txt

Узнать объём директории:
    du -sh /home/user
-s -  напечатать только суммарный объём файлов
-р - в удобном для чтения виде

Поиск всех файлов с именем test
    find / -name test

Вернуться в домашнюю директорию:
    cd

Сделать что-либо со всеми файлами в папке, например, распаковать все zip архивы в текущей папке:
    for f in *.zip ; do unzip $f ; done

Архиваторы [help.ubuntu]
Архиваторы bzip2 и gzip не способны обрабатывать несколько файлов, поэтому файлы для архивирования часто помещают в один контейнер - несжатый архив tar,  который непосредственно уже можно сжимать.

Сжатие -c архиватором gzip -z в файл с именем z.tar.gz. Файлы которые нужно сжать указываются последнем параметром
tar -сzf z.tar.gz file1 file2 file3
Просмотр -t содержимого архива (добавить ключ -v для подробных сведениях о файлах):
tar -tf z.tar.bz
Распаковка архива:
tar -xf z.tar.bz 
или распаковка в каталог -С:
tar -xf z.tar.bz -С /extract/here

Изображения

Удалить EXIF данные и перезаписать файл [exif]
exiftool -overwrite_original -all= image.jpg
Изменить размер изображение в два раза и увеличить степень сжатия (с потерями)
convert -resize 50% -quality 80 image.jpg image-new.jpg

Железо

Средствами "из коробки" показать всю информацию о железе в одном месте и в удобном для человека виде можно, но для этого придётся запускать несколько программ и возможно обрабатывать их вывод [more, подробнее]. 
Поэтому чтобы просто и наглядно представить данные о аппаратном обеспечении нужно установить дополнительный пакет: inxi.
Программа умеет показывать многое [more], но необходимый минимум информации можно посмотреть вызвав:
inxi -Fx
dmesg - показывает буффер сообщений ядра, среди которых может быть информация о вновь подключённых устройствах.
Ключи:
-H - вывод в более читаемом виде (например использование относительного времени для сообщений);
-w - вывод в реальном времени.
lshw - консольная утилита рассказывающая о аппаратном обеспечении, можно импортировать вывод программы в html;
lshw-gtk - то же самое но с графическим интерфейсом.
Программу нужно запускать от имени сеперпользователя, иначе информация может быть скудной.

HardInfo - менне детальная информация, дружелюбный интерфейс.

lspci - печатает информацию о PCI шинах и подключённых к ним устройствах (в том числе USB).

WiFi

iw list

lspci | grep -i network
 
Узнать состояние аккумулятора наутбука
acpi -b 
Battery 0: Full, 100%
acpi -V  # вся информация
***
cat /sys/class/power_supply/BAT1/capacity
***
upower -i /org/freedesktop/UPower/devices/battery_BAT1

Антивирус

Свободный CalmAV  - обладает достаточно скромными возможностями по сравнению с популярными антивирусами. Это скорее сканер чем полноценный антивирус, хоть он и может работать в режиме демона. Поэтому для полноценной защиты его будет недостаточно.
Обновить базу (требуются права суперпользователя):
freshclam
Сканировать файл:
clamscan файл
Рекурсивно сканировать папку:
clamscan -r Downloads
При этом в вывод попадут все просканированные файлы. Чтобы напечатать только заражённые файлы необходимо использовать ключ --infected.
Графическая оболочка для антивируса - clamtk.
Об эффективности антивируса в сравнении с другими http://www.shadowserver.org/wiki/pmwiki.php/Stats/VirusYearlyStats

Программа chkrootkit предназначена для поиска руткитов. Установка, настройка и использование сканера уязвимостей chkrootkit

GPG

gpg -c <file>     - encrypt the file with password
gpg <file>        - decrypt

http://wiki.linuxformat.ru/wiki/LXF117:GPG
http://wikiadmin.net/gnupg/

***

=== windows ===
chntpw - registry editor

Регулярные выражения etc

Показать строки содержашие mytext
cat myfile | grep mytext
text1 ИЛИ text2:
cat myfile | grep -e text1 -e text2 
показать 5 строк до и после
cat myfile | grep -e text1 -С 5
Показать всё, кроме
... | grep -v some_text
Показать только текст совпадающий с шаблоном (-o)
... | grep -o some_regexp
Grep Cheat Sheet


***
Вычислить md5 хэш

echo -n "[eqyz" | openssl md5


Программирование etc

Отформатировать код на Pascal\Delphi:
ptop src.pas new_src.pas
Утилита ptop входит в состав FPC.

***
Интерпретатор JavaScript в консоли - rhino

***
Увидеть содержимое файла в шестнадцатеричном виде:
xxd файл
hexdump файл
 Иногда полезно вывести файл в виде набора значений байт. Добавим ключ -e с описанием соответствующего формата:
' [iterations]/[byte_count] "[format string]" '
Применяет строку формата format string к группам байт по byte_count штук iterations раз. format string описывается подобно формату функции printf.
hexdump -ve '1/1 "%x"' ave.txt
-v - не пропускать повторяющие данные (hexdump заменяет их сиволом *)
%x - печатать шестнадцатеричные значения

Регулярные выражения

Памятка
Регулярные выражения для валидации распространенных видов данных


=== apt-get ===
sud    apt-get install openssh-server mc vim gedit links2 git python galculator  codeblocks gnuplot deluge vlc marble stellarium lynx thunderbird  wxmaxima lazarus synaptic gnome-tweak-tool shutter blender inkscape gimp file-roller virtualbox stardict xneur texlive kile mcabber keepass2 clementine texmaker texlive-lang-cyrillic xdotool pidgin celestia cmus jabref screen stardict sshfs goldendict

apt-get install samba libpam-smbpass sshfs firefox-mozilla-build gpg gauke truecrypt 

apt-get install nmap wireshark hydra crunch aircrack-ng  metasploit mtr bkhive samdump2 chntpw dsniff sslstrip ettercap-text-only ngrep tshark dsniff ettercap-graphical ettercap-text-only

Переменные пользователя в bash

Переменная создаётся в момент присваивания значения: 
myvar=1234
myvar2='Ave Statanas'
Пробелы вокруг оператора присваивания = недопустимы.
Чтобы обратится к переменной, перед её именем нужно поставить знак $.
Печать содержимого переменной: echo $myvar2

Сылки