Пример 1: с помощью ключевого слова del
В этом примере мы создадим DataFrame, а затем удалим указанный столбец с помощью ключевого слова del. Столбец выбирается для удаления с помощью метки столбца.
import pandas as pd mydictionary = {'names': , 'physics': , 'chemistry': , 'algebra': } #create dataframe df_marks = pd.DataFrame(mydictionary) print('Original DataFrame\n--------------') print(df_marks) #delete a column del df_marks print('\n\nDataFrame after deleting column\n--------------') print(df_marks)
Вывод:
Original DataFrame -------------- names physics chemistry algebra 0 Somu 68 84 78 1 Kiku 74 56 88 2 Amol 77 73 82 3 Lini 78 69 87 DataFrame after deleting column -------------- names physics algebra 0 Somu 68 78 1 Kiku 74 88 2 Amol 77 82 3 Lini 78 87
Мы удалили столбец химии из DataFrame.
Метод – 5: Dataframe из списка dicts
Мы можем передать списки словарей в качестве входных данных для создания фрейма данных Pandas. Имена столбцов по умолчанию используются в качестве ключей.
Пример –
# the example is to create # Pandas DataFrame by lists of dicts. import pandas as pd # assign values to lists. data = # Creates DataFrame. df = pd.DataFrame(data) # Print the data print(df)
Выход:
A B C x y z 0 10.0 20.0 30.0 NaN NaN NaN 1 NaN NaN NaN 100.0 200.0 300.0
Давайте разберемся в другом примере создания фрейма данных pandas из списка словарей с индексом строки и индексом столбца.
Пример – 2:
import pandas as pd # assigns values to lists. data = # With two column indices, values same # as dictionary keys dframe1 = pd.DataFrame(data, index =, columns =) # With two column indices with # one index with other name dframe2 = pd.DataFrame(data, index =, columns =) # print the first data frame print(dframe1, "\n") # Print the second DataFrame. print(dframe2)
Выход:
x y first 1.0 2.0 second NaN NaN x y1 first 1.0 NaN second NaN NaN
Рассмотрим пример создания фрейма данных путем передачи списков словарей и строк.
Пример – 3:
# The example is to create # Pandas DataFrame by passing lists of # Dictionaries and row indices. import pandas as pd # assign values to lists data = # Creates padas DataFrame by passing # Lists of dictionaries and row index. dframe = pd.DataFrame(data, index =) # Print the dataframe print(dframe)
Выход:
x y z first 2 NaN 3 second 10 20.0 30
Мы обсудили три способа создания фрейма данных с использованием списков словаря.
Создание набора данных
Как обычно, перед изучением работы метода drop() в многоиндексных датафреймах, необходимо создать такой, для чего можно использовать следующий код.
В этом примере данные были созданы с помощью функции np.arange() в сочетании с np.reshape() для получения матрицы 6 на 6.
После этого необходимо создать мультииндексы для столбцов и строк.
Существуют различные способы сделать это, но в примере он был создан из кортежей с помощью функции pd.MultiIndex.from_tuples().
После получения мультииндексных объектов dataframe создается обычным способом, используя эти элементы вместо векторов для индексов строк и столбцов.
Удаление строк или столбцов верхнего уровня
Исключение строк или столбцов первого уровня выполняется так же, как и в стандартном случае.
Просто используйте метод drop() объекта, указав в свойстве columns имя удаляемых столбцов или колонок и, аналогично, свойство index для строк.
Таким образом, для удаления столбца B и строки Y вы можете использовать следующую строку кода.
В качестве альтернативы, для удаления строк можно указать только имя строки в методе drop().
В случае со столбцами этого также можно добиться, указав имя и присвоив свойству axis значение 1.
Это требует одного шага для удаления столбцов и другого для строк.
С другой стороны, если вы хотите удалить более одного столбца или строки, вам просто нужно передать вектор с индексами, которые вы хотите удалить.
Поэтому для удаления столбцов A и B одновременно со строками X и Z вы можете ввести следующую команду.
Пример 2
В этом примере мы попытаемся удалить столбец, которого нет в DataFrame.
Когда вы пытаетесь удалить несуществующий столбец с помощью pop(), функция выдает ошибку KeyError.
import pandas as pd mydictionary = {'names': , 'physics': , 'chemistry': , 'algebra': } #create dataframe df_marks = pd.DataFrame(mydictionary) print('Original DataFrame\n--------------') print(df_marks) #delete column that is not present df_marks.pop('geometry') print('\n\nDataFrame after deleting column\n--------------') print(df_marks)
Вывод:
В этом руководстве на примерах Python мы узнали, как удалить столбец из DataFrame с помощью pop() с помощью хорошо подробных примеров программ.
Удаление столбцов или строк мультииндекса
Теперь, в случае, если мы хотим удалить столбцы C2 второго уровня, использование того, что было объяснено до сих пор, приведет к ошибке.
Чтобы избежать этого, необходимо указать через свойство level функции drop(), что вы хотите удалить столбец второго уровня.
То есть, присвоив свойству значение 1, как показано ниже.
На самом деле, в этом есть большой смысл, поскольку в случае, когда один и тот же тег используется в двух разных уровнях, Pandas не может знать, какой из них удалить. Поэтому необходимо указать уровень, на котором вы хотите его применить, если он не первый.
В случае с рядами процесс аналогичен предыдущему.
Как и для индексов первого уровня, также возможно удаление строк и столбцов с помощью одной инструкции. Однако они должны быть одного уровня.
Пример 2: со значением по умолчанию
В этом примере мы создадим df_marks и добавим новый столбец с именем geometry со значением по умолчанию для каждой строки в DataFrame.
import pandas as pd mydictionary = {'names': , 'physics': , 'chemistry': , 'algebra': } #create dataframe df_marks = pd.DataFrame(mydictionary) print('Original DataFrame\n--------------') print(df_marks) #add column df_marks = 65 print('\n\nDataFrame after adding "geometry" column\n--------------') print(df_marks)
Вывод:
Original DataFrame -------------- names physics chemistry algebra 0 Somu 68 84 78 1 Kiku 74 56 88 2 Amol 77 73 82 3 Lini 78 69 87 DataFrame after adding "geometry" column -------------- names physics chemistry algebra geometry 0 Somu 68 84 78 65 1 Kiku 74 56 88 65 2 Amol 77 73 82 65 3 Lini 78 69 87 65
Столбец добавляется в DataFrame с указанным значением в качестве значения столбца по умолчанию.
Импорт данных
Начнем симпорта библиотек и датасетов. В работе будем использовать датасет с ценами на недвижимость Бостона, доступный в библиотеке Scikit-learn.
import numpy as np # линейная алгебраimport pandas as pd # обработка данных, CSV файл ввода-вывода (например, pd.read_csv)from sklearn.datasets import load_bostonboston = load_boston()df = pd.DataFrame(data=boston.data,columns=boston.feature_names)df=boston.targetdf.head()
Данный содержит только числовые признаки, а нам нужны категориальные переменные для разделения датасета на группы. Следовательно, займемся их созданием с помощью его описательной статистики:
df.describe()
Допустим, нам нужны категориальные признаки для RM (число комнат) и price (цены), которые представляют собой среднее число комнат на жилое помещение и медиану цен на жилье в размере $10,000 соответственно. В зависимости от диапазона значений указанных числовых признаков у этих переменных должны быть разные уровни (level), для создания которых задействуем значения первого и третьего квантиля. С целью генерирования этих новых переменных воспользуемся функцией .
df=df.apply(lambda x: 'low' if x<5.8 else 'middle' if x<6.6 else 'high')df=df.apply(lambda x: 'low' if x<17 else 'middle' if x<25 else 'high')df].head()
Новые столбцы появились благодаря функции , которая по умолчанию работает с каждой строкой датасета. Она по порядку проверяет условия. Первый уровень содержит значения числовых признаков, не превышающих первый квантиль. “Средний” уровень включает значения, располагающиеся в диапазоне между первым и третьим квантилем. Третий и последний уровень охватывают только значения, превосходящие третий квантиль.
Функция — альтернативный и более эффективный способ создания таких переменных, в особенности тех, что обладают несколькими уровнями. Как и в предыдущем случае, делим значения price на 3 группы: [3,5.8),[5.8,6.6),[6.6,9), где 3 и 9 соответствуют минимальной и максимальной границам переменной. Эту же логику применяем и к числу комнат. Передав только интервальные значения и аргумент для игнорирования правого максимума, получаем следующие группы:
df = pd.cut(df,bins=,right=False)df = pd.cut(df,bins=,right=False)df].head()
При необходимости сохранить эти метки учитывайте тот факт, что несмотря на категориальный тип новых столбцов, отдельные элементы являются не строками, а объектами ! Попытка осуществить поиск конкретного класса значений окажется безрезультатной.
df
Если проверить тип столбца , взяв лишь первую строку, то увидим, что у нас есть на самом деле:
type(df)
Если вы намерены сохранить эти интервалы, то во избежание сложностей подскажу один прием — передайте метку для каждой группы, установив аргумент со списком строк:
l=,]lbs1 = ,l) for i in range(len(l)-1)]lbs2 = ,l) for i in range(len(l)-1)]df = pd.cut(df,bins=,right=False,labels=lbs1)df = pd.cut(df,bins=,right=False,labels=lbs2)print(type(df))
Теперь у вас есть строковые объекты! В любом случае в данной статье я буду сохранять метки, как показано ниже, всегда устанавливая аргумент :
df = pd.cut(df,bins=,labels=,right=False)df = pd.cut(df,bins=,labels=,right=False)
Данные¶
Чтобы проиллюстрировать некоторые примеры, я собираюсь использовать необычный набор данных из переписи белок Центрального парка. Да, видимо, в Центральном парке пытались подсчитать и занести в каталог белок. Я подумал, что это будет забавный пример для работы.
Этот набор данных включает 3023 строки данных и 31 столбец. Хотя 31 столбец не является огромным количеством столбцов, это полезный пример для иллюстрации концепций, которые вы можете применить к данным с большим количеством столбцов.
В октябре 2018 года с помощью добровольцев-охотников за белками подсчитали количество белок в Центральном парке Нью-Йорка. В результате переписи белок был выпущен отчет. Параметры, включенные в отчет:
- : координата долготы точки наблюдения за белкой
- : Координата широты точки наблюдения за белкой
- : идентификационный ярлык для каждой обнаруженной белки. Тег состоит из + + (MMDD) + .
- : ID тег, полученный из сетки гектаров, используемой для разделения и подсчета парковой зоны. Одна ось, которая проходит преимущественно с севера на юг, является числовой (1-42), а ось, которая проходит преимущественно с востока на запад, является алфавитной (A-I).
- : значение — или , чтобы указать, когда произошло наблюдение — утром или поздно вечером.
- : объединение месяца, дня и года наблюдения (MMDDYYYY).
- : число в хронологической последовательности наблюдений за белками для отдельного наблюдения.
- : значение (Взрослый) or (Несовершеннолетний).
- : , или .
- : дискретное значение или строковые значения, состоящие из , , или .
- : комбинация двух предыдущих столбцов; в этом столбце приведены общие наблюдаемые перестановки основных цветов и оттенков.
- : иногда наблюдатели добавляли комментарии о состоянии беличьего меха.
- : или . Наблюдателям было дано указание отметить, где была белка, когда ее впервые заметили.
- : — для наблюдений за белками на плоскости земли.
- : Иногда наблюдатели добавляли комментарии о местонахождении белки.
- : была замечена бегущая белка.
- : белка, преследующая другую белку.
- : белка, взбирающаяся на дерево или другой природный объект.
- : белка за едой.
- : белка в поисках пищи.
- : другая активность белки.
- : веселое голосовое общение, используемое белками по разным причинам.
- : удлиненное голосовое общение, которое может указывать на присутствие наземного хищника, такого как собака.
- : высокий голос, который может указывать на присутствие воздушного хищника, такого как ястреб.
- : белка, ловящая хвост. Используется для увеличения размера белки и сбивания с толку соперников или хищников.
- : используется белкой для выражения интереса, любопытства.
- : белка, приближающаяся к человеку в поисках еды.
- : белке было безразлично присутствие человека.
- : белка убегает от людей, считая их угрозой.
- : наблюдатель отмечает другие типы взаимодействий между белками и людьми.
Уверен, теперь вы узнали много нового о поведении белок!
Множественные агрегации
С целью выполнения множественных агрегаций для нескольких столбцов потребуется функция , позволяющая применить среднее, минимальное и максимальное значения, а также стандартное отклонение для каждого выбранного столбца. Результаты сгруппируем по типу цены.
df_price = df.groupby(by=,as_index=False)].agg()df_price
Как видно, при добавлении функции аргумент более не работает. Во избежание использования метки группы в качестве индекса можно в конце поместить функцию :
df_price = df.groupby(by=)].agg().reset_index()df_price
Теперь все признаки агрегированы, но при работе с этим датасетом могут возникнуть проблемы. Выбирая конкретный признак, вы должны указывать двойные индексы:
df_price.columns
Работа с двойными индексами может стать обременительной. Чтобы не создавать лишних сложностей, можно заменить имена столбцов следующим образом:
stats = df_price.columns = +++df_price
С таким работается уже намного легче.
Передача словаря в функцию позволит применять различные статистики в зависимости от столбца. В этом случае ключами будут имена столбцов, а значениями — агрегированная функция, подлежащая измерению. На этот раз для группировки датасета нам понадобятся два признака:
df_price = df.groupby(by=,as_index=False).agg({'CRIM':,'price':})df_price
Отразим новые итоги обработки данных в гистограмме. Сначала поменяем метки датасета, а затем посмотрим на результаты для жилья с наибольшим числом комнат.
import plotly.express as pxstats = df_price.columns = ++df_pricefig = px.bar(df_price, x='price_levels', y='CRIM_count', labels={'price_levels':'Price','CRIM_count':'Count of observations'})fig.show()
Очевидно, что число домов увеличивается с ростом цены, поскольку мы выбрали большое количество комнат. Налицо прямая зависимость между числом комнат и ценой дома.
Почему мы заботимся о выборе столбцов?¶
Во многих стандартных примерах, встречающихся в науке о данных, относительно небольшое число столбцов. Например, в наборе данных их 8, у — 4, а у — 14. Реальные же наборы данных — грязные и часто включают множество дополнительных (потенциально ненужных) столбцов.
В процессе анализа данных вам может потребоваться выбрать подмножество столбцов по следующим причинам:
- Фильтрация для включения отдельных столбцов позволяет уменьшить объем памяти и ускорить обработку данных.
- Ограничение количества столбцов может уменьшить накладные расходы, связанные с хранением модели данных в вашей голове (см. Магическое число семь плюс-минус два).
- При изучении нового набора данных может потребоваться разбить задачу на управляемые части.
- В некоторых случаях может потребоваться перебрать столбцы и выполнить вычисления или очистку, чтобы получить данные в формате, необходимом для дальнейшего анализа.
- Ваши данные могут содержать лишнюю или повторяющуюся информацию.
Описанные ниже приемы помогут сократить время, которое вы тратите на обработку столбцов данных.
Метод 1: использование astype()
DataFrame.astype() приводит этот DataFrame к указанному типу данных. Ниже приводится синтаксис метода.
astype(dtype, copy=True, errors='raise', **kwargs)
Нас интересует только первый аргумент dtype – это тип данных или dict имени столбца.
Итак, давайте использовать метод astype() с аргументом dtype, чтобы изменить тип данных одного или нескольких столбцов DataFrame.
Как изменить тип данных одного столбца?
Давайте сначала начнем с изменения типа данных только для одного столбца.
В следующей программе мы изменим тип данных столбца a на float.
import pandas as pd import numpy as np #initialize a dataframe df = pd.DataFrame( , , , ], columns=) print('Previous Datatypes\n', df.dtypes, sep='') #change datatype of column df = df.astype({'a': np.float}) #print results print('\nNew Datatypes\n', df.dtypes, sep='') print('\nDataFrame\n', df, sep='')
Вывод:
Previous Datatypes a int64 b int64 c int64 dtype: object New Datatypes a float64 b int64 c int64 dtype: object DataFrame a b c 0 21.0 72 67 1 23.0 78 62 2 32.0 74 54 3 52.0 54 76
Как изменить тип данных нескольких столбцов?
Теперь давайте изменим тип данных более чем для одного столбца. Все, что нам нужно сделать, это предоставить больше пар column_name: datatype key:value в аргументе метода astype().
В следующей программе мы изменим тип данных столбца a на float, а b на int8.
import pandas as pd import numpy as np #initialize a dataframe df = pd.DataFrame( , , , ], columns=) print('Previous Datatypes\n', df.dtypes, sep='') #change datatype of column df = df.astype({'a': np.float, 'b': np.int8}) #print results print('\nNew Datatypes\n', df.dtypes, sep='') print('\nDataFrame\n', df, sep='')
Вывод:
Previous Datatypes a int64 b int64 c int64 dtype: object New Datatypes a float64 b int8 c int64 dtype: object DataFrame a b c 0 21.0 72 67 1 23.0 78 62 2 32.0 74 54 3 52.0 54 76
Как изменить тип данных всех столбцов?
Если вы хотите изменить тип данных всех столбцов DataFrame, вы можете просто передать этот тип данных в качестве аргумента методу astype() без словаря.
В следующей программе мы изменим тип данных всех столбцов на float.
import pandas as pd import numpy as np #initialize a dataframe df = pd.DataFrame( , , , ], columns=) print('Previous Datatypes\n', df.dtypes, sep='') #change datatype of column df = df.astype(np.float) #print results print('\nNew Datatypes\n', df.dtypes, sep='') print('\nDataFrame\n', df, sep='')
Вывод:
Previous Datatypes a int64 b int64 c int64 dtype: object New Datatypes a float64 b float64 c float64 dtype: object DataFrame a b c 0 21.0 72.0 67.0 1 23.0 78.0 62.0 2 32.0 74.0 54.0 3 52.0 54.0 76.0
Простые агрегации
Итак, первый этап пройден, и мы приступаем к группировке датасета на основании заданных признаков. Допустим, нужно узнать среднее значение каждого столбца для каждого типа price:
df_price = df.groupby(by=).mean()df_price
Как видно, по каждому уровню мы получили строку, содержащую соответствующие средние значения всех переменных, представленных в датасете. Переменная считается индексом, поскольку по умолчанию в качестве такого индекса возвращает метку группы
Обратите внимание на произвольный порядок уровней. Выясним причину:
df.info()
На данный момент новые переменные сохранены в памяти как объекты. Очевидно, что их необходимо преобразовать в категории. Как только мы это сделали, определяем порядок уровней переменных.
df=df.astype('category')df.cat.reorder_categories(, inplace=True)df=df.astype('category')df.cat.reorder_categories(, inplace=True)
Попробуем заново сгруппировать датасет для каждого уровня price. Если установить аргумент в значение , то метка группы более не будет рассматриваться в качестве индекса:
df_price = df.groupby(by=,as_index=False).mean()df_price
В результате получаем упорядоченные уровни и переменную , которая более не является индексом. Как видим, датасет содержит много столбцов. Их число можно сократить, если выбрать лишь несколько признаков (например, RM и price). Кроме того, расположим ценовые уровни по возрастанию.
df_price = df.groupby(by=,as_index=False)].mean().sort_values(by='price_levels', ascending=True)df_price
С увеличением числа комнат повышается стоимость жилплощади. Но что если мы не хотим ограничиваться вычислением среднего, минимального и максимального значений? В таком случае нам потребуется функция . Выясним диапазон значений столбцов CRIM и LSTAT, имена которых соответственно означают уровень преступности на душу населения по городу и процент граждан с низким социальным статусом.
df_price = df.groupby(by=,as_index=False)].apply(lambda v: v.max()-v.min())df_price
Как видно, уровень преступности и процент населения с низким социальным положением уменьшаются с ростом цен на жилплощадь. Представим это соотношение в виде гистограммы:
import plotly.express as pxfig = px.bar(df_price, x='price_levels', y='CRIM', labels={'price_levels':'Price','CRIM':'Range of Criminality'})fig.show()