Обложка статьи «Задачи по Data Science от Tproger и GeekBrains»

Задачи по Data Science от Tproger и GeekBrains

Партнёрский материал. Что это?

Вместе с факультетом Data Science GeekUniversity собрали для вас задачи для практики по самым популярным Python-библиотекам в Data Science: pandas, NumPy и DataTable. Решать задачи можно в любом порядке.

Обратите внимание, что у любой задачи может быть несколько способов решения. Чтобы посмотреть добавленный нами вариант решения, кликните по соответствующей кнопке. Все приведённые варианты написаны на Python 3.

Задачи по pandas

Задача 1

Как найти евклидово расстояние между двумя Series (точками) a и b, не используя встроенную формулу?

Ввод:

a = pd.Series([2, 4, 6, 8])
b = pd.Series([1, 3, 5, 7])

Ожидаемый вывод:

2.0
# Ввод
a = pd.Series([2, 4, 6, 8]
b = pd.Series([1, 3, 5, 7])

# Решение 
sum((a - b)**2)**.5

# Решение (с использованием функции из NumPy)
np.linalg.norm(a-b)

Задача 2

Как найти максимально возможное абсолютное значение корреляции каждого столбца с другими столбцами в df?

Ввод:

df = pd.DataFrame(np.random.randint(1, 100, 16).reshape(4, 4), columns=list('efgh'), index=list('abcd'))
# Ввод
df = pd.DataFrame(np.random.randint(1, 100, 16).reshape(4, 4), columns=list('efgh'), index=list('abcd'))

# Решение
abs_corr = np.abs(df.corr())
max_corr = abs_corr.apply(lambda x: sorted(x)[-2])
print('Максимальное значение корреляции для каждого столбца: ', np.round(max_corr.tolist(), 2))

Вывод:

Максимальное значение корреляции для каждого столбца:  [0.58 0.58 0.76 0.76]

Задача 3

Как нормализовать все столбцы в DataFrame?

  1. Нормализуйте все столбцы df путём вычитания среднего значения столбца и деления на стандартное отклонение.
  2. Сделайте так, чтобы все значения в df находились в диапазоне от 0 до 1.

Ввод:

df = pd.DataFrame(np.random.randint(1, 100, 16).reshape(4, 4))
# Ввод
df = pd.DataFrame(np.random.randint(1, 100, 16).reshape(4, 4))

# Первая часть решения
part1 = df.apply(lambda x: ((x - x.mean()) / x.std()).round(2))
print('Первая часть\n', part1)

# Вторая часть решения
part2 = df.apply(lambda x: ((x.max() - x) / (x.max() - x.min())).round(2))
print('Вторая часть\n', part2)

Вывод:

Первая часть
       0     1     2     3
0 -1.11 -0.87  0.43  0.61
1 -0.57  0.83 -0.50 -0.38
2  0.72  0.91 -1.09 -1.23
3  0.96 -0.87  1.17  0.99
Вторая часть
       0     1     2     3
0  1.00  1.00  0.33  0.17
1  0.74  0.05  0.74  0.62
2  0.12  0.00  1.00  1.00
3  0.00  1.00  0.00  0.00

Задача 4

Как объединить два DataFrame по двум столбцам так, чтобы остались только общие строки?

Объедините df1 и df2 по столбцам fruit-frukt и weight-ves.

Ввод:

df1 = pd.DataFrame({'fruit': ['apple', 'banana', 'orange'] * 3,
                    'weight': ['low', 'medium', 'high'] * 3,
                    'price': np.random.randint(0, 100, 9)})

df2 = pd.DataFrame({'frukt': ['apple', 'banana', 'melon'] * 2,
                    'ves': ['low', 'high'] * 3,
                    'price': np.random.randint(0, 100, 6)})
# Ввод
df1 = pd.DataFrame({'fruit': ['apple', 'banana', 'orange'] * 3,
                    'weight': ['low', 'medium', 'high'] * 3,
                    'price': np.random.randint(0, 100, 9)})

df2 = pd.DataFrame({'frukt': ['apple', 'banana', 'melon'] * 2,
                    'ves': ['low', 'high'] * 3,
                    'price': np.random.randint(0, 100, 6)})

# Решение
pd.merge(df1, df2, how='inner', left_on=['fruit', 'weight'], right_on=['frukt', 'ves'], suffixes=['_left', '_right'])

Задача 5

Как узнать частоту уникальных значений во всём DataFrame?

Ввод:

df = pd.DataFrame(np.random.randint(1, 10, 16).reshape(4, 4), columns=list('abcd'))
# Ввод
df = pd.DataFrame(np.random.randint(1, 10, 16).reshape(4, 4), columns=list('abcd'))

# Решение
pd.value_counts(df.values.ravel())

Вывод:

2    5
8    4
9    2
6    2
5    1
3    1
1    1
dtype: int64

Задача 6

Как создать новый столбец, который содержит номера ближайших по евклидовому расстоянию столбцов?

Ввод:

df = pd.DataFrame(np.random.randint(1, 100, 16).reshape(4, 4), columns=list('efgh'), index=list('abcd'))
df
#     e   f   g   h
# a  51  57  11  15
# b  63   5  81  48
# c   7  63  98  88
# d   6  31  29  37

Ожидаемый вывод:

df
#     e   f   g   h nearest_row   dist
# a  51  57  11  15           c  122.0
# b  63   5  81  48           a   94.0
# c   7  63  98  88           a  122.0
# d   6  31  29  37           c   92.0
# Ввод
df = pd.DataFrame(np.random.randint(1, 100, 16).reshape(4, 4), columns=list('efgh'), index=list('abcd'))

import numpy as np

# Инициализация выводов
nearest_rows = []
nearest_distance = []

# Проход по строкам
for i, row in df.iterrows():
    curr = row
    rest = df.drop(i)
    dists = {}  # инициализируем словарь для евклидовых расстояния для текущей строки
    # проходим по оставшимся строкам текущей строки
    for j, contestant in rest.iterrows():
        # вычисляем евклидово расстояние и обновляем dists
        
        dists.update({j: round(np.linalg.norm(curr.values - contestant.values))})
    # приравниваем текущую строку к ближайшей и записываем значение расстояния=
    nearest_rows.append(max(dists, key=dists.get))
    nearest_distance.append(max(dists.values()))

df['nearest_row'] = nearest_rows
df['dist'] = nearest_distance

Задачи по NumPy

Задача 7

Как поменять местами две строки в двумерном массиве NumPy? Поменяйте местами строки 1 и 3 массива a.

Ввод:

a = np.arange(9).reshape(3,3)
# Ввод
a = np.arange(9).reshape(3,3)

# Решение
a[[2, 1, 0], :]

Вывод:

array([[6, 7, 8],
       [3, 4, 5],
       [0, 1, 2]])

Задача 8

Как найти количество уникальных значений в массиве NumPy? Найдите уникальные значения и их количество в столбце species таблицы iris.

Ввод:

url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris = np.genfromtxt(url, delimiter=',', dtype='object')
# Ввод
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris = np.genfromtxt(url, delimiter=',', dtype='object')

# Решение
# Извлекаем столбец species как массив
species = np.array([row.tolist()[4] for row in iris])

# Получаем уникальные значения и их количество
np.unique(species, return_counts=True)

Вывод:

(array([b'Iris-setosa', b'Iris-versicolor', b'Iris-virginica'],
       dtype='|S15'), array([50, 50, 50]))

Задача 9

Как найти второе максимальное значение в массиве, который сгруппирован по другому массиву? Найдите значение второго самого длинного petallength вида setosa в таблице iris.

Ввод:

url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris = np.genfromtxt(url, delimiter=',', dtype='object')

Решение:

# Ввод
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris = np.genfromtxt(url, delimiter=',', dtype='object')

# Решение
# Извлекаем столбцы вида и длины лепестков
setosa_petal_len = iris[iris[:, 4] == b'Iris-setosa', [2]].astype('float')

# Получаем второе значение с конца
np.unique(np.sort(setosa_petal_len))[-2]

Вывод:

1.7

Задача 10

Как отранжировать элементы массива NumPy?

Ввод:

a = np.random.randint(100, size=10)
print(a)
# [9 15 64 28 89 93 29 8 73 0]

Ожидаемый вывод:

[2 3 6 4 8 9 5 1 7 0]
# Ввод
a = np.random.randint(100, size=10)

# Решение
print(a.argsort().argsort())

Задача 11

Как найти результат деления минимального значения на максимальное в каждой строке двумерного массива?

Ввод:

np.random.seed(10)
a = np.random.randint(1, 10, [3, 3])
a
# array([[5, 1, 2],
#        [1, 2, 9],
#        [1, 9, 7]])
# Ввод
np.random.seed(10)
a = np.random.randint(1, 10, [3, 3])

# Решение
np.apply_along_axis(lambda x: np.min(x) / np.max(x), arr=a, axis=1)

Вывод:

array([0.2, 0.11111111, 0.11111111])

Задача 12

Как найти повторяющиеся значения в массиве NumPy? Найдите повторяющиеся значения (начиная со второго вхождения) в заданном массиве и отметьте их как True. Первое вхождение отмечайте как False.

Ввод:

np.random.seed(10)
a = np.random.randint(0, 7, 10)
print(a)
# [1 5 4 0 1 3 4 1 5 0]

Ожидаемый вывод:

[False False False False True False True True True True]
# Ввод
np.random.seed(10)
a = np.random.randint(0, 7, 10)

# Решение

# Создаём массив с True
out = np.full(a.shape[0], True)

# Находим индексы уникальных элементов
pos = np.unique(a, return_index=True)[1]

# Помечаем их как False
out[pos] = False

print(out)

Задача 13

Как удалить из массива NumPy строки, которые содержат nan?

Ввод:

url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris = np.genfromtxt(url, delimiter=',', dtype='float', usecols=[0, 1, 2, 3])
iris[np.random.randint(150, size=20), np.random.randint(4, size=20)] = np.nan

Решение:

# Ввод
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris = np.genfromtxt(url, delimiter=',', dtype='float', usecols=[0, 1, 2, 3])
iris[np.random.randint(150, size=20), np.random.randint(4, size=20)] = np.nan

# Решение
# Способ 1:
nan_in_row = np.array([~np.any(np.isnan(row)) for row in iris])
iris[nan_in_row][:5]

# Способ 2:
iris[np.sum(np.isnan(iris), axis = 1) == 0][:5]

Вывод:

array([[ 4.9,  3. ,  1.4,  0.2],
       [ 4.7,  3.2,  1.3,  0.2],
       [ 4.6,  3.1,  1.5,  0.2],
       [ 5. ,  3.6,  1.4,  0.2],
       [ 5.4,  3.9,  1.7,  0.4]])

Задачи по DataTable

Задача 14

Как сделать left join двух объектов datatable.Frame? Объедините заданные объекты по ключу А.

Ввод:

import datatable as dt
df1 = dt.Frame(A=[1, 2, 3, 4], B=['a', 'b', 'c', 'd'])
df2 = dt.Frame(A=[1, 2, 3, 4, 5], C=['a2', 'b2', 'c2', 'd2', 'e2'])
# Ввод
import datatable as dt
df1 = dt.Frame(A=[1, 2, 3, 4], B=['a', 'b', 'c', 'd'])
df2 = dt.Frame(A=[1, 2, 3, 4, 5], C=['a2', 'b2', 'c2', 'd2', 'e2'])

# Решение
df2.key = 'A'
output = df1[:, :, dt.join(df2)]

Задача 15

Как преобразовать datatable.Frame в формат Pandas, NumPy, словаря, списка, кортежа, CSV-файла? Датасет из примера.

Решение:

import datatable as dt
df = dt.fread('https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv')

# в DataFrame Pandas
pd_df = df.to_pandas()

# в массив NumPy
arr = df.to_numpy()

# в словарь
dict_ = df.to_dict()

# в список
list_ = df[:, 'medv'].to_list()

# в кортеж
tuples_ = df[:, 'medv'].to_tuples()

# в CSV 
df.to_csv('BostonHousing.csv')

Задача 16

Как узнать типы данных всех столбцов в datatable.Frame? Датасет из примера.

Ожидаемый вывод:

crim : stype.float64
zn : stype.float64
indus : stype.float64
chas : stype.bool8
nox : stype.float64
rm : stype.float64
age : stype.float64
dis : stype.float64
rad : stype.int32
tax : stype.int32
ptratio : stype.float64
b : stype.float64
lstat : stype.float64
medv : stype.float64

Решение:

import datatable as dt

df = dt.fread('https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv')
for i in range(len(df.names)):
    print(df.names[i], ':', df.stypes[i])

Рекламные публикации для бизнеса:
sales@tproger.ru, +7 916 559-71-10

Tproger