In [9]:
#Изменение рабочей папки
import os
os.chdir('C:\Disk d\Kaggle\Homesite')

#Импорт библиотеки
import pandas as pd
In [5]:
#задание ширины/высоты таблиц при выводе
pd.set_option('max_columns',20)
In [15]:
pd.set_option('max_rows',5)
In [2]:
pd.set_option('max_columns',20,'max_rows',20)

Импорт текстовых файлов с разделителем

In [13]:
#Простой вариант
#все параметры файла берутся по умолчанию.
small=pd.read_csv('small.csv')  

small - объект типа DataFrame, по-сути это таблица, или 2-мерный массив NumPy. Только с названиями столбцов и индексом строк.

In [14]:
small.head(3)                   #метод head(n) возвращает n первых строк
Out[14]:
QuoteNumber Original_Quote_Date QuoteConversion_Flag Field6 Field7 ... GeographicField61B GeographicField62A GeographicField62B GeographicField63 GeographicField64
0 1 2013-08-16 0 B 23 ... 18 -1 10 N CA
1 2 2014-04-22 0 F 7 ... 17 -1 20 N NJ
2 4 2014-08-25 0 F 7 ... 11 -1 8 N NJ

3 rows × 299 columns

По умолчанию read_csv берёт первую строку файла в качестве имён столбцов. Если файл не содержит заголовка, то можно сказать об этом и он сгенерируется.

In [17]:
small=pd.read_csv('small.csv',',',header=None)
small.head()                                 #head по умолчанию выводит 5 первых строк
Out[17]:
0 1 2 3 4 ... 294 295 296 297 298
0 QuoteNumber Original_Quote_Date QuoteConversion_Flag Field6 Field7 ... GeographicField61B GeographicField62A GeographicField62B GeographicField63 GeographicField64
1 1 2013-08-16 0 B 23 ... 18 -1 10 N CA
2 2 2014-04-22 0 F 7 ... 17 -1 20 N NJ
3 4 2014-08-25 0 F 7 ... 11 -1 8 N NJ
4 6 2013-04-15 0 J 10 ... 9 -1 21 N TX

5 rows × 299 columns

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

Немного нагруженные варианты

In [22]:
#Явно задаём разделитель     ','
#Отказываемся от названий столбцов     header=None
#Строка 0 с именами столбцов из файла нам не нужна - используем параметр    skiprows=[0]
#Дату попросим распознать как дату - используем параметр     parse_dates=[1]
small=pd.read_csv('small.csv',',',header=None, skiprows=[0], parse_dates=[1])
small.head(4)
Out[22]:
0 1 2 3 4 5 6 7 8 9 ... 289 290 291 292 293 294 295 296 297 298
0 1 2013-08-16 0 B 23 0.9403 0.0006 965 1.0200 N ... 9 9 -1 8 -1 18 -1 10 N CA
1 2 2014-04-22 0 F 7 1.0006 0.0040 548 1.2433 N ... 10 10 -1 11 -1 17 -1 20 N NJ
2 4 2014-08-25 0 F 7 1.0006 0.0040 548 1.2433 N ... 15 18 -1 21 -1 11 -1 8 N NJ
3 6 2013-04-15 0 J 10 0.9769 0.0004 1,165 1.2665 N ... 6 5 -1 10 -1 9 -1 21 N TX

4 rows × 299 columns

In [ ]:
#Интересный случай, 3-я строка в файле:
0.9769,0.0004,"1,165",1.2665
#т.е. в файле есть поле "1,165" содержащее в себе разделитель, но при этом выделенное кавычками
quotechar = '"' #позволит игнорировать разделитель внутри кавычек, хотя pandas сделал это автоматически выше
#конкретно в этом случае полезен параметр разделителя тысячных разрядов:
thousands = ','
#Можно применять сложные конвертеры на столбец. Например, для замены символов:
converters={'salary': lambda x: float(x.replace('$', ''))}      #salary - это название столбца
In [23]:
#А теперь сделаем это
#Обратите внимание на строку 3 столбец 7. Как видите, всё корректно распарсилось (цифра 1165)
small=pd.read_csv('small.csv',',',header=None, skiprows=[0], parse_dates=[1],quotechar = '"',thousands = ',')
small.head()
Out[23]:
0 1 2 3 4 5 6 7 8 9 ... 289 290 291 292 293 294 295 296 297 298
0 1 2013-08-16 0 B 23 0.9403 0.0006 965 1.0200 N ... 9 9 -1 8 -1 18 -1 10 N CA
1 2 2014-04-22 0 F 7 1.0006 0.0040 548 1.2433 N ... 10 10 -1 11 -1 17 -1 20 N NJ
2 4 2014-08-25 0 F 7 1.0006 0.0040 548 1.2433 N ... 15 18 -1 21 -1 11 -1 8 N NJ
3 6 2013-04-15 0 J 10 0.9769 0.0004 1165 1.2665 N ... 6 5 -1 10 -1 9 -1 21 N TX
4 8 2014-01-25 0 E 23 0.9472 0.0006 1487 1.3045 N ... 18 22 -1 10 -1 11 -1 12 N IL

5 rows × 299 columns

In [25]:
#Можно не применять thousands = ',' и использовать конвертер на столбец 7:
small=pd.read_csv('small.csv',',',header=None, skiprows=[0], parse_dates=[1],quotechar = '"', converters={7: lambda x: x.replace(',', '')})
small.head(4)
Out[25]:
0 1 2 3 4 5 6 7 8 9 ... 289 290 291 292 293 294 295 296 297 298
0 1 2013-08-16 0 B 23 0.9403 0.0006 965 1.0200 N ... 9 9 -1 8 -1 18 -1 10 N CA
1 2 2014-04-22 0 F 7 1.0006 0.0040 548 1.2433 N ... 10 10 -1 11 -1 17 -1 20 N NJ
2 4 2014-08-25 0 F 7 1.0006 0.0040 548 1.2433 N ... 15 18 -1 21 -1 11 -1 8 N NJ
3 6 2013-04-15 0 J 10 0.9769 0.0004 1165 1.2665 N ... 6 5 -1 10 -1 9 -1 21 N TX

4 rows × 299 columns

In [ ]:
#Прочие параметры reas_csv смотрите тут:
#http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html#pandas.read_csv

Элементарная аналитика

In [24]:
#встроенные методы
small.info()
small.dtypes
small.describe()
small.head(n)
small.tail(n)     #n записей с конца
<class 'pandas.core.frame.DataFrame'>
Int64Index: 991 entries, 0 to 990
Columns: 299 entries, 0 to 298
dtypes: datetime64[ns](1), float64(6), int64(266), object(26)
memory usage: 2.2+ MB
In [ ]:
#Обращение к строкам/столбцам/ячейкам DataFrame отличается от ndArray
small[20:22]      #возвращает строки 20 и 21, со строками всё просто, срезы работают
small[[7]]        #возвращает столбец 7, но сделать срез не получится

Группировки

In [15]:
grp=small.groupby(7)   #группировки по столбцу 7
In [16]:
grp.count().head(3)    #кол-во ненулевых значений по каждом столбце
Out[16]:
0 1 2 3 4 5 6 8 9 10 ... 289 290 291 292 293 294 295 296 297 298
7
548 143 143 143 143 143 143 143 143 143 143 ... 143 143 143 143 143 143 143 143 143 143
564 120 120 120 120 120 120 120 120 120 120 ... 120 120 120 120 120 120 120 120 120 120
935 214 214 214 214 214 214 214 214 214 214 ... 214 214 214 214 214 214 214 214 214 214

3 rows × 298 columns

In [18]:
grp.size().head(3)    #количество строк для каждой группы
Out[18]:
7
548    143
564    120
935    214
dtype: int64
In [19]:
grp.sum().head(3) #сумма по столбцам
Out[19]:
0 2 4 5 6 8 10 11 12 13 ... 287 288 289 290 291 292 293 294 295 296
7
548 107244 49 1507 142.2261 0.5720 176.4019 1165 1771 1162 1759 ... 1495 1662 1894 2214 13 2011 -117 1838 -91 1950
564 96115 38 1252 115.5469 0.4560 138.0438 1004 1469 1020 1490 ... 1254 1374 1714 1988 -42 1626 -68 1611 -68 1557
935 166837 50 4943 196.8492 0.1498 218.2800 2047 2975 2063 2983 ... 2726 3047 2560 2818 -84 2645 46 3057 20 3106

3 rows × 271 columns

In [20]:
grp.mean().head(3)   #среднее
Out[20]:
0 2 4 5 6 8 10 11 12 13 ... 287 288 289 290 291 292 293 294 295 296
7
548 749.958042 0.342657 10.538462 0.994588 0.0040 1.233580 8.146853 12.384615 8.125874 12.300699 ... 10.454545 11.622378 13.244755 15.482517 0.090909 14.062937 -0.818182 12.853147 -0.636364 13.636364
564 800.958333 0.316667 10.433333 0.962891 0.0038 1.150365 8.366667 12.241667 8.500000 12.416667 ... 10.450000 11.450000 14.283333 16.566667 -0.350000 13.550000 -0.566667 13.425000 -0.566667 12.975000
935 779.612150 0.233645 23.098131 0.919856 0.0007 1.020000 9.565421 13.901869 9.640187 13.939252 ... 12.738318 14.238318 11.962617 13.168224 -0.392523 12.359813 0.214953 14.285047 0.093458 14.514019

3 rows × 271 columns

In [21]:
grp.median()[3:6]     #медиана, срез с 3 по 5 строку
Out[21]:
0 2 4 5 6 8 10 11 12 13 ... 287 288 289 290 291 292 293 294 295 296
7
965 935.5 0 23 0.9403 0.0006 1.0200 8 14 8 14 ... 12 14 11 12 -1 14.0 -1 14 -1 14
1113 855.5 0 23 0.8870 0.0004 1.2665 7 12 7 12 ... 11 13 9 9 -1 11.5 -1 10 -1 14
1165 734.0 0 20 0.9691 0.0004 1.2665 8 13 8 13 ... 12 14 10 10 -1 12.0 -1 10 -1 16

3 rows × 271 columns

In [ ]:
 

Заполнение null-ов

In [16]:
import pandas as pd
import os
os.chdir('C:\Disk d\Kaggle\Winton')

train = pd.read_csv('train.csv')
In [14]:
#посмотрим, есть ли null-ы
train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 69999 entries, 0 to 69998
Data columns (total 5 columns):
Field7     69999 non-null int64
Field8     69999 non-null float64
Field6     69999 non-null object
Field9     69999 non-null float64
Field10    69999 non-null int64
dtypes: float64(2), int64(2), object(1)
memory usage: 2.9+ MB
In [17]:
# тривиальное заполнение нулями
train.fillna(value=0, inplace=True)
In [18]:
# чуть менее тривиальное заполнение каждой фичи её медианным значением
med=train.median()
train.fillna(value=med, inplace=True)
Out[18]:
Id Feature_1 Feature_2 Feature_3 Feature_4 Feature_5 Feature_6 Feature_7 Feature_8 Feature_9 ... Ret_175 Ret_176 Ret_177 Ret_178 Ret_179 Ret_180 Ret_PlusOne Ret_PlusTwo Weight_Intraday Weight_Daily
0 1 0 0.000000 0.000000 0.000000 8 0.000000 75751 0.2254 11 ... -0.002688 0.002246 -0.000838 -6.953224e-04 0.000003 -0.001974 -0.019512 0.028846 1251507.965681 1564384.957101
1 2 0 0.000000 0.000000 0.000000 3 0.388896 17369 0.0166 13 ... -0.000129 0.000123 0.000248 3.315418e-07 0.000003 0.000027 -0.002939 -0.010253 1733950.349065 2167437.936331
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
39998 39999 0 -0.021457 1.021284 0.000000 3 1.092849 27376 0.2119 13 ... 0.000273 0.000017 0.000247 -1.384585e-04 0.000015 -0.000123 -0.018877 -0.011572 1507917.515694 1884896.894617
39999 40000 0 1.093868 -0.677391 -0.604479 7 0.000000 4141 0.2254 0 ... -0.000914 -0.002752 0.001351 9.032382e-04 0.003667 0.002761 0.024405 -0.024345 1535389.455406 1919236.819257

40000 rows × 211 columns

Перевод категориальных (как правило текстовых) features в цифровые

In [1]:
import pandas as pd
import numpy as np
from sklearn import preprocessing
import os
os.chdir('C:\Disk d\Kaggle\Homesite')

train = pd.read_csv('train_new.csv',thousands=',')
In [33]:
#посмотрим какие фичи имеют текстовые значения, как правило они и есть категориальные, нуждаются в переводе в числа.
train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 50000 entries, 0 to 49999
Columns: 299 entries, QuoteNumber to GeographicField64
dtypes: float64(6), int64(265), object(28)
memory usage: 109.1+ MB

Видим что 28 столбцов нуждаются в конвертации.

Тривиальный вариант, каждой категории (текстовому значению) присваивается число:

In [ ]:
# допустим у нас раздельно test и train
test=train[50000:]
train=train[:50000]
In [34]:
# Используем LabelEncoder
for f in train.columns:
    if train[f].dtype=='object':
        lbl = preprocessing.LabelEncoder()
        lbl.fit(list(train[f].values) + list(test[f].values))
        train[f] = lbl.transform(list(train[f].values))
        test[f] = lbl.transform(list(test[f].values))

OneHot. Более чоткий вариант, создающий для каждого значения категориальной (текстовой) фичи отдельную фичу-индикатор.

Готовый вариант от старших товарищей: https://gist.github.com/kljensen/5452382. Только не работает. А так-то написано круто, профессионально.

In [18]:
# здесь не будем разделять train и test, так будет удобнее потом написать процедуру
train = pd.read_csv('train_new.csv',thousands=',')
train=train[['Field7','Field8','Field6','Field9','Field10']] #оставим две категориальные фичи - Field6 и Field7
In [19]:
#составим список текстовых категориальных полей
features=[u for u in train.columns if train[u].dtype=='object']
features
Out[19]:
['Field6']
In [20]:
#добавим числовые категориальные поля, которые предыдущий скрипт не подцепил
features.append('Field7')
features
Out[20]:
['Field6', 'Field7']
In [21]:
# Используем LabelEncoder чтобы перевести текст в int
for f in features:
    lbl = preprocessing.LabelEncoder()
    lbl.fit(list(train[f].values))
    train[f] = lbl.transform(list(train[f].values))
In [22]:
# Вынесем категориальные фичи в отдельный DataFrame
train_cat=train[features]
train_num=train.drop(features,axis=1)
In [23]:
#Добавим столбец нулей, потому что OneHotEncoder крючит когда ему на вход подают одну фичу
train_cat=train_cat.join(pd.DataFrame(np.zeros(len(train_cat)), columns=['Zeros5136363000LOL']))
In [24]:
enc = preprocessing.OneHotEncoder(sparse=False)
nd_onehot=enc.fit_transform(train_cat)
In [25]:
enc.n_values_ #количество уникальных значений (категорий) для каждой из фич
Out[25]:
array([ 8, 28,  1])
In [26]:
enc.feature_indices_ # индексы, ограничивающие фичи при развёртке в индикаторы
# то есть первая фича, у которой 8 значений, будет иметь индекс от 0 до 7, вторая фича от 8 и т.д.
Out[26]:
array([ 0,  8, 36, 37], dtype=int32)
In [27]:
# Сделаем красивые названия для столбцов
fnames=[]
for i in range(len(features)):
    for j in range(enc.n_values_[i]):
        fnames.append(str(features[i])+'_'+str(j))
In [28]:
train_onehot=train_num.join(pd.DataFrame(nd_onehot[:,:-1], columns=fnames))
train_onehot
Out[28]:
Field8 Field9 Field10 Field6_0 Field6_1 Field6_2 Field6_3 Field6_4 Field6_5 Field6_6 ... Field7_18 Field7_19 Field7_20 Field7_21 Field7_22 Field7_23 Field7_24 Field7_25 Field7_26 Field7_27
0 0.9403 0.0006 965 0 1 0 0 0 0 0 ... 0 0 0 0 1 0 0 0 0 0
1 1.0006 0.0040 548 0 0 0 0 0 1 0 ... 0 0 0 0 0 0 0 0 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
69997 0.9153 0.0007 935 0 1 0 0 0 0 0 ... 0 0 0 0 0 0 1 0 0 0
69998 0.9838 0.0040 548 0 0 0 0 0 1 0 ... 0 0 0 0 0 0 0 0 0 0

69999 rows × 39 columns

In [ ]:
 
In [9]:
# А теперь сделаем это всё процедурой
#####################################
# dataset - DataFrame, входное множество
# features - список с названиями категориальных столбцов
# если список не задан, то ищутся все фичи типа object и принимаются за категориальные
def OneHot(dataset, features=[]):
    if len(features)==0:
        features=[u for u in dataset.columns if dataset[u].dtype=='object']
    dataset_cat=dataset[features].join(pd.DataFrame(np.zeros(len(dataset)), columns=['Zeros5136363000LOL']))
    dataset_num=dataset.drop(features,axis=1)
    for f in features:
        lbl = preprocessing.LabelEncoder()
        dataset_cat[f] = lbl.fit_transform(list(dataset_cat[f].values))
    enc = preprocessing.OneHotEncoder(sparse=False)
    nd_onehot=enc.fit_transform(dataset_cat)
    fnames=[]
    for i in range(len(features)):
        for j in range(enc.n_values_[i]):
            fnames.append(str(features[i])+'_'+str(j))
    return dataset_num.join(pd.DataFrame(nd_onehot[:,:-1], columns=fnames))
In [15]:
# проверяем
OneHot(train, ['Field6'])
Out[15]:
Field7 Field8 Field9 Field10 Field6_0 Field6_1 Field6_2 Field6_3 Field6_4 Field6_5 Field6_6 Field6_7
0 23 0.9403 0.0006 965 0 1 0 0 0 0 0 0
1 7 1.0006 0.0040 548 0 0 0 0 0 1 0 0
... ... ... ... ... ... ... ... ... ... ... ... ...
69997 25 0.9153 0.0007 935 0 1 0 0 0 0 0 0
69998 11 0.9838 0.0040 548 0 0 0 0 0 1 0 0

69999 rows × 12 columns

In [ ]:
 
In [ ]:
 
In [21]:
 
In [ ]:
 

Отрисовка

Вы можете не подгружать matplotlib и сразу отрисовывать из pandas, но matplotlib должен быть установлен.

In [7]:
#пример с matplotlib, просто как проверочный
import numpy as np
import matplotlib.pyplot as plt
%pylab inline                    # самая важная штука!!!!!!!!!1111111111111111
%matplotlib inline               # или так
x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.plot(x, y)
Populating the interactive namespace from numpy and matplotlib
Out[7]:
[<matplotlib.lines.Line2D at 0x6dcbd70>]
In [10]:
# пример отрисовки
small=read_csv('small.csv',',',header=None, skiprows=[0], parse_dates=[1],quotechar = '"',thousands = ',')
small=small[[0]]          #отрисовываем только один столбец 0
small.plot(style='k--')   #за ось Х берется индекс, за ось Y значение в столбце 0
Out[10]:
<matplotlib.axes._subplots.AxesSubplot at 0x6dcb090>
In [17]:
# ещё пример отрисовки
small=read_csv('small.csv',',',header=None, skiprows=[0], parse_dates=[1],quotechar = '"',thousands = ',')
small.head(50).plot(x=1,y=2,kind='bar',figsize=(16,4))    # за ось Х берется столбец 1, за ось Y значение в столбце 2
                                                          # figsize задаёт размер выводимой области, (ширина,высота) - в дюймах
Out[17]:
<matplotlib.axes._subplots.AxesSubplot at 0x8ac0190>
In [24]:
# ещё пример отрисовки
small=read_csv('small.csv',',',header=None, skiprows=[0], parse_dates=[1],quotechar = '"',thousands = ',')
grp=small.groupby(7)
grp.size().plot(kind='pie',figsize=(4,4))
Out[24]:
<matplotlib.axes._subplots.AxesSubplot at 0x8595950>
In [ ]: