Skip to content

Instantly share code, notes, and snippets.

@dsibi
Last active January 25, 2023 21:08
Show Gist options
  • Save dsibi/505ce65b612056a4e65f7af4e56903fb to your computer and use it in GitHub Desktop.
Save dsibi/505ce65b612056a4e65f7af4e56903fb to your computer and use it in GitHub Desktop.
yandex_python_data_analyst_4_Условия и функции
Разобьём элементы таблиц на группы и проанализируем их свойства.
Чему вы научитесь
Создавать функции, фильтровать данные и пользоваться условным оператором.
Сколько времени это займёт
4 часа: 17 уроков примерно по 14 минут.
Постановка задачи
Каждый год Американская киноакадемия вручает премию «Оскар» за лучший фильм. Проанализируем фильмы, получившие эту премию за последние 30 лет, и посмотрим, как менялись предпочтения киноакадемии за это время.
Мы собрали данные о последних 30 кинофильмах, получивших «Оскар» как самый лучший фильм.
НАЗВАНИЕ ГОД РЕЙТИНГ ДЛИНА, МИН. ЖАНР БЮДЖЕТ, $ МЛН СБОРЫ, $ МЛН
Форма воды 2017 6.914 123 фантастика, драма 19.4 195.243464
Лунный свет 2016 6.151 110 драма 1.5 65.046687
В центре внимания 2015 7.489 129 драма, криминал, история 20.0 88.346473
Бёрдмэн 2014 7.604 119 драма, комедия 18.0 103.215094
12 лет рабства 2013 7.71 133 драма, биография, история 20.0 178.371993
Операция «Арго» 2012 7.517 120 триллер, драма, биография 44.5 232.324128
Артист 2011 7.942 96 драма, мелодрама, комедия 15.0 133.432856
Король говорит! 2010 7.977 118 драма, биография, история 15.0 414.211549
Повелитель бури 2008 7.298 126 триллер, драма, военный, история 15.0 49.230772
Миллионер из трущоб 2008 7.724 120 драма, мелодрама 15.0 377.910544
Старикам тут не место 2007 7.726 122 триллер, драма, криминал 25.0 171.627166
Отступники 2006 8.456 151 триллер, драма, криминал 90.0 289.847354
Столкновение 2004 7.896 108 триллер, драма, криминал 6.5 98.410061
Малышка на миллион 2004 8.075 132 драма, спорт 30.0 216.763646
Властелин колец: Возвращение Короля 2003 8.617 201 фэнтези, драма, приключения 94.0 1119.110941
Чикаго 2002 7.669 113 мюзикл, комедия, криминал 45.0 306.776732
Игры разума 2001 8.557 135 драма, биография, мелодрама 58.0 313.542341
Гладиатор 2000 8.585 155 боевик, драма, приключения 103.0 457.640427
Красота по-американски 1999 7.965 122 драма 15.0 356.296601
Влюбленный Шекспир 1998 7.452 123 драма, мелодрама, комедия, история 25.0 289.317794
Титаник 1997 8.369 194 драма, мелодрама 200.0 2185.372302
Английский пациент 1996 7.849 155 драма, мелодрама, военный 27.0 231.976425
Храброе сердце 1995 8.283 178 драма, военный, биография, история 72.0 210.409945
Форрест Гамп 1994 8.915 142 драма, мелодрама 55.0 677.386686
Список Шиндлера 1993 8.819 195 драма, биография, история 22.0 321.265768
Непрощенный 1992 7.858 131 драма, вестерн 14.4 159.157447
Молчание ягнят 1990 8.335 114 триллер, криминал, детектив, драма, ужасы 19.0 272.742922
Танцующий с волками 1990 8.112 181 драма, приключения, вестерн 22.0 424.208848
Шофёр мисс Дэйзи 1989 7.645 99 драма 7.5 145.793296
Человек дождя 1988 8.25 133 драма 25.0 354.825435
Было бы интересно определить лидеров по разным параметрам: например, по рейтингу и бюджету. Для этого воспользуемся сортировкой.
# Python получает статистику как список списков, который
# хранится в переменной oscar_data (от англ. Oscar data,
# "данные Оскара").
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
print('# Самый высокий рейтинг')
print()
# Чтобы отсортировать по рейтингу, указываем значением
# лямбда-функции (ключа сортировки) третий (с индексом 2)
# элемент каждого списка. Это и есть показатель рейтинга.
# Порядок сортировки указываем по убыванию.
oscar_data.sort(key=lambda row: row[2], reverse=True)
# для краткости столбец с жанром не печатаем
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in oscar_data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
print()
print()
print('# Самый большой бюджет')
print()
oscar_data.sort(key=lambda row: row[5], reverse=True)
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in oscar_data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
print()
# Самый высокий рейтинг
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Форрест Гамп | 1994 | 8.91 | 142 | 55.0 | 677.4 |
Список Шиндлера | 1993 | 8.82 | 195 | 22.0 | 321.3 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Игры разума | 2001 | 8.56 | 135 | 58.0 | 313.5 |
# Самый большой бюджет
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Титаник | 1997 | 8.37 | 194 | 200.0 | 2185.4 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Отступники | 2006 | 8.46 | 151 | 90.0 | 289.8 |
Храброе сердце | 1995 | 8.28 | 178 | 72.0 | 210.4 |
Ещё раз взглянем на код вывода таблицы на экран:
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in oscar_data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
print()
Чтобы вывести таблицу на экран второй раз, нам пришлось скопировать код. Так лучше не делать, потому что:
Любое изменение в скопированном коде придётся делать в каждом повторении. Это повышает риск ошибки.
Тому, кто будет читать код, придётся разбираться заново в каждом повторении.
Если фрагмент кода понадобится не однажды, ему дают имя. Получается функция. Логику её работы прописывают один раз, а затем вызывают всюду, где она нужна.
Напишем функцию для перевода длительности фильма из минут в часы. Помните, что у функции print() есть аргумент — строка, которую она печатает? У нашей функции тоже будет аргумент — длительность фильма в минутах. Функция проведёт с ним расчёты и напечатает результат на экране:
def print_length_hours(minutes):
hours = minutes / 60
print('Длительность: {:.2f} часов.'.format(hours))
# для наглядности функции отделяют от остального кода двумя переносами
print('Форма воды')
print_length_hours(123)
print()
print('Шофёр мисс Дэйзи')
print_length_hours(99)
print()
Форма воды
Длительность: 2.05 часов.
Шофёр мисс Дэйзи
Длительность: 1.65 часов.
Мы описали логику работы функции, а потом дважды её вызвали. Ключевое слово def указывает на начало определения функции. Здесь мы снова столкнулись с отступами в 4 пробела: они выделяют тело функции — код, который эта функция будет выполнять.
image
Аргумент minutes — это по сути переменная внутри функции. Её значение заранее не известно — оно задаётся в скобках при вызове функции. В зависимости от этого значения на экране печатается подходящий текст.
TASK
В таблице бюджеты указаны в долларах. Напишите функцию print_budget_in_rubles(), которая переводит их в рубли и печатает на экране. Используйте курс 1$ = 67.01₽.
Функция должна принимать сумму в долларах как аргумент и выводить на экран результат в формате:
Бюджет: 13402.00 млн ₽
Обратите внимание: сумма выводится с двумя знаками после запятой.
SOLUTION
# Записываем курс в переменной rubles_for_dollar
# (англ. rubles for dollar, "рублей за доллар").
rubles_for_dollar = 67.01
def print_budget_in_rubles(dollars):
rubles = dollars*rubles_for_dollar
print('Бюджет: {:.2f} млн ₽'.format(rubles))
print('Титаник')
print_budget_in_rubles(200.0)
print()
print('Гладиатор')
print_budget_in_rubles(103.0)
Одного аргумента функции часто не хватает для сложных задач. В этом уроке мы приведём пример такой задачи и покажем, как делать функции с несколькими аргументами.
Начнём с того, что напишем функцию для печати на экране первых 5 элементов таблицы.
def print_top5(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
Обратите внимание на отступы для цикла в коде функции. Мы вложили цикл в её тело, и поэтому тело такого цикла набирается с отступом уже не в 4 пробела, а в 8.
Теперь вызовем нашу функцию: она печатает на экране топовые (по рейтингу и бюджету) фильмы.
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
print('# Самый высокий рейтинг')
print()
oscar_data.sort(key=lambda row: row[2], reverse=True)
print_top5(oscar_data)
print()
print()
print('# Самый большой бюджет')
print()
oscar_data.sort(key=lambda row: row[5], reverse=True)
print_top5(oscar_data)
print()
print()
# Самый высокий рейтинг
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Форрест Гамп | 1994 | 8.91 | 142 | 55.0 | 677.4 |
Список Шиндлера | 1993 | 8.82 | 195 | 22.0 | 321.3 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Игры разума | 2001 | 8.56 | 135 | 58.0 | 313.5 |
# Самый большой бюджет
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Титаник | 1997 | 8.37 | 194 | 200.0 | 2185.4 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Отступники | 2006 | 8.46 | 151 | 90.0 | 289.8 |
Храброе сердце | 1995 | 8.28 | 178 | 72.0 | 210.4 |
Улучшим нашу функцию: пусть она сама сортирует таблицу. Чтобы это сделать, пропишем в коде ещё один аргумент (количество теоретически не ограничено). Этим вторым аргументом станет индекс столбца, по которому мы хотим сортировать. Указывают его в скобках после первого аргумента. Пусть в объявлении функции этот параметр будет называться column:
def print_top5_by_column(data, column):
...
Тогда для сортировки по столбцу с индексом 3 функцию нужно вызвать так:
print_top5_by_column(oscar_data, 3)
Обратите внимание: мы переименовали функцию в соответствии с её целью. Имена аргументов тоже понятно описывают, для чего те нужны.
Напишем тело функции и обновим код печати таблицы:
def print_top5_by_column(data, column):
data.sort(key=lambda row: row[column], reverse=True)
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
Используем её, чтобы вывести информацию и по другим столбцам:
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
print('# Самый высокий рейтинг')
print()
print_top5_by_column(oscar_data, 2)
print()
print()
print('# Самый большой бюджет')
print()
print_top5_by_column(oscar_data, 5)
print()
print()
print('# Самые большие сборы')
print()
print_top5_by_column(oscar_data, 6)
print()
print()
print('# Самая большая длина')
print()
print_top5_by_column(oscar_data, 3)
print()
print()
# Самый высокий рейтинг
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Форрест Гамп | 1994 | 8.91 | 142 | 55.0 | 677.4 |
Список Шиндлера | 1993 | 8.82 | 195 | 22.0 | 321.3 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Игры разума | 2001 | 8.56 | 135 | 58.0 | 313.5 |
# Самый большой бюджет
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Титаник | 1997 | 8.37 | 194 | 200.0 | 2185.4 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Отступники | 2006 | 8.46 | 151 | 90.0 | 289.8 |
Храброе сердце | 1995 | 8.28 | 178 | 72.0 | 210.4 |
# Самые большие сборы
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Титаник | 1997 | 8.37 | 194 | 200.0 | 2185.4 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Форрест Гамп | 1994 | 8.91 | 142 | 55.0 | 677.4 |
Гладиатор | 2000 | 8.59 | 155 | 103.0 | 457.6 |
Танцующий с волками | 1990 | 8.11 | 181 | 22.0 | 424.2 |
# Самая большая длина
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
Список Шиндлера | 1993 | 8.82 | 195 | 22.0 | 321.3 |
Титаник | 1997 | 8.37 | 194 | 200.0 | 2185.4 |
Танцующий с волками | 1990 | 8.11 | 181 | 22.0 | 424.2 |
Храброе сердце | 1995 | 8.28 | 178 | 72.0 | 210.4 |
TASK_1_3
Мы продолжили улучшать функцию print_top5_by_column() и добавили в неё возможность изменять порядок сортировки. Для этого мы дописали ещё один аргумент reverse. Он имеет такой же смысл, как аргумент reverse метода sort(): принимает значение False, если нужно сортировать в обычном порядке, и True — если в обратном.
После добавления нового аргумента написанные ранее вызовы функций перестали работать. Проблема в том, что функция теперь принимает три аргумента, а мы передаём только два. Исправьте эти вызовы, передав им третий аргумент (он будет равен True, так как мы по-прежнему хотим видеть бо́льшие значения наверху). Затем выведите на экран 5 самых коротких фильмов из таблицы (третьим аргументом будет False, чтобы наверху были короткие фильмы, а не длинные).
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def print_top5_by_column(data, column, reverse):
data.sort(key=lambda row: row[column], reverse=reverse)
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
# обновите код вывода топовых значений
print('# Самый высокий рейтинг')
print()
print_top5_by_column(oscar_data, 2, True)
print()
print()
print('# Самый большой бюджет')
print()
print_top5_by_column(oscar_data, 5, True)
print()
print()
print('# Самые большие сборы')
print()
print_top5_by_column(oscar_data, 6,True)
print()
print()
print('# Самая большая длина')
print()
print_top5_by_column(oscar_data, 3,True)
print()
print()
# добавьте вывод самых коротких фильмов
print('# Самая маленькая длина')
print()
print_top5_by_column(oscar_data, 3,False)
print()
print()
TASK_2_3
Напишите функцию print_profit(), которая вычисляет и выводит на экран прибыль, полученную от фильма. Прибыль вычисляется как разность сборов (выручки) и бюджета. Функция должна принимать значения бюджета и сборов как аргументы (первый аргумент — бюджет, второй аргумент — сборы). Названия для аргументов выберите самостоятельно. Результат должен печататься на экране с двумя знаками после запятой и без сопроводительного текста.
В прекоде мы привели пример использования этой функции.
SOLUTION
def print_profit(budjet,revenue):
profit=revenue-budjet
print("{:.2f}".format(profit))
print("Прибыль от фильма «Титаник»:")
print_profit(200.0, 2185.372302)
TASK_3_3
Напишите функцию print_mean(), которая считает и выводит на экран среднее значение по заданному столбцу. Функция должна принимать два аргумента —data (таблицу) и column (номер столбца). Результат должен печататься на экране с двумя знаками после запятой и без сопроводительного текста.
После создания функции можно посчитать средние значения по большинству столбцов. Мы уже сделали это в прекоде.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def print_mean(data, column):
total = 0
for row in data:
# чтобы получить нужное значение, напишите row[column]
total += row[column]
mean = total / len(data)
print('{:.2f}'.format(mean))
print('Средний рейтинг: ', end='')
print_mean(oscar_data, 2)
print('Средняя длина: ', end='')
print_mean(oscar_data, 3)
print('Средний бюджет: ', end='')
print_mean(oscar_data, 5)
print('Средние сборы: ', end='')
print_mean(oscar_data, 6)
Сейчас наши функции печатают результаты своей работы на экране. После этого мы никак не можем использовать значения, которые они считали. Как правило, это неудобно: например, не получится сохранить среднее в переменную для других расчётов.
Поэтому функции умеют возвращать значение — передавать результат, который можно сохранить в переменной. Давайте, например, переделаем функцию пересчёта долларов в рубли и обновим код для печати бюджета в рублях:
rubles_for_dollar = 67.01
def dollars_to_rubles(dollars):
rubles = dollars * rubles_for_dollar
return rubles
titanic_dollars = 200.0
titanic_rubles = dollars_to_rubles(titanic_dollars)
print('Бюджет фильма "Титаник": {:.2f} млн ₽'.format(titanic_rubles))
Бюджет фильма "Титаник": 13402.00 млн ₽
Ключевое слово return указывает, какое значение вернёт функция. Например, dollars_to_rubles() возвращает сохранённое в переменной rubles произведение.
Функция работает по тому же принципу, что и такси — всегда выполняет один и тот же набор действий:
приезжает (адрес отправления — первый аргумент);
отвозит (пункт назначения — второй аргумент);
выставляет счёт (стоимость — возвращаемое значение).
Если функция это такси, то вызов функции — вызов такси:
адреса отправления и прибытия — это значения аргументов: они определяются в момент вызова;
стоимость поездки — это возвращаемое значение.
TASK 1_3
Посчитаем суммарные бюджет и сборы фильмов из таблицы. Напишите функцию column_sum(), которая получает на вход таблицу и номер столбца, и возвращает сумму значений по этому столбцу. Используйте эту функцию, чтобы напечатать результат в таком формате:
Суммарный бюджет: ... млн $
Суммарные сборы: ... млн $
Суммы выводите с точностью до двух знаков после запятой.
Напоминаем, что бюджет хранится в столбце с индексом 5, а сборы — с индексом 6.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def column_sum(data, column):
result=0
for row in data:
result+=row[column]
return result
total_budget = column_sum(oscar_data, 5)
print('Суммарный бюджет: {:.2f} млн $'.format(total_budget))
total_gross = column_sum(oscar_data, 6)
print('Суммарные сборы: {:.2f} млн $'.format(total_gross))
TASK 2_3
Представим, что каждый человек посмотрел все оскаровские фильмы. Сколько тогда пришлось бы отдать за каждый билет в кино, чтобы обеспечить кинокартинам сборы не меньше нынешних?
Чтобы найти эту величину, нужно суммарные сборы всех фильмов в таблице (столбец с индексом 6) поделить на численность земного населения. По данным Бюро переписи населения США за 2018 год на Земле проживают 7539 миллионов человек. Суммарные сборы вам поможет найти функция из предыдущего задания. Поделите одно на другое и результат выведите на экран вот в таком виде:
Каждый человек в среднем потратил $... на фильмы, получившие "Оскар".
Как и прежде, нужная точность — два знака после запятой.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def column_sum(data, column):
result = 0
for row in data:
result += row[column]
return result
# (англ. total people, "всего людей"). Остальным двум переменным - для
# суммы затрат и для потраченного на душу населения - можете дать любые
# имена по своему вкусу.
total_people = 7539
total_gross = column_sum(oscar_data, 6)
spent_per_person = total_gross / total_people
print('Каждый человек в среднем потратил ', end='')
print('${:.2f} на фильмы, получившие "Оскар".'.format(spent_per_person))
TASK 3_3
Функция print_mean(), которую вы писали в прошлом уроке, находит среднее значение и выводит его на экран. Измените код этой функции так, чтобы вместо печати на экране она возвращала найденное среднее.
Для подсчёта суммы не пишите цикл — вызывайте функцию column_sum(). Переиспользование кода — хорошая практика.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def column_sum(data, column):
result = 0
for row in data:
result += row[column]
return result
def column_mean(data, column):
total=column_sum(data, column)
mean=total/len(data)
return mean
mean_score = column_mean(oscar_data, 2)
print('Средний рейтинг: {:.2f}'.format(mean_score))
mean_length = column_mean(oscar_data, 3)
print('Средняя длина: {:.2f} мин.'.format(mean_length))
mean_budget = column_mean(oscar_data, 5)
print('Средний бюджет: {:.2f} млн $'.format(mean_budget))
mean_gross = column_mean(oscar_data, 6)
print('Средние сборы: {:.2f} млн $'.format(mean_gross))
Мы будем часто создавать функции. Давайте немного разберёмся в их устройстве, чтобы избежать неприятных сюрпризов. Вроде таких:
# предположим, что бюджет фильма состоит из двух частей: в долларах и в рублях
rubles = 1200
dollars = 65
# какова будет сумма в рублях?
# определим функцию для перевода долларов в рубли
rubles_for_dollar = 67.01
def dollars_to_rubles(dollars):
# мы опечатались в названии переменной rubles
rubls = dollars * rubles_for_dollar
# это строка всё равно работает, но использует не ту переменную
return rubles
total = rubles + dollars_to_rubles(dollars)
print("Суммарный бюджет: {:.2f} млн ₽".format(total))
# бюджет на самом деле: 5555.65 млн ₽
Суммарный бюджет: 2400.00 млн ₽
Всё дело в объявлении переменных. Функция, встречая переменную, пытается найти её значение в своём же коде. Если находит — пользуется, если нет — начинает смотреть «снаружи», в коде программы. Получается, если и внутри, и снаружи от функции есть переменные с одинаковыми именами, будет использована та, что внутри.
Мы объявили переменную rubles вне функции, а затем хотели объявить переменную с таким же именем внутри. Из-за опечатки функция не нашла значение внутри себя и пошла смотреть снаружи. Нашла и вернула нам. Функция отработала хорошо, но получилось совсем не то, чего мы хотели.
Избежать таких проблем поможет знание о глобальных и локальных переменных. Глобальные переменные — это те, что объявлены вне функций. К ним можно обращаться откуда угодно. Отсюда и название.
Соответственно, переменные, объявленные внутри функции, — локальные. К ним обратиться из кода вне тела функции нельзя.
Не давайте локальным и глобальным переменным одинаковые имена — опечатки потом очень трудно искать в коде.
def column_sum(data, column):
result = 0
for row in data:
result += row[column]
return result
# Переменная result — локальная. Обращение к ней
# снаружи от функции приводит к ошибке:
print(result)
Traceback (most recent call last):
File "main.py", line 7, in <module>
print(result)
NameError: name 'result' is not defined
Локальные переменные можно сравнить с людьми, находящимися с вами в одной комнате, а глобальные — со знакомыми, чей номер телефона у вас есть. Вы можете обратиться к любому человеку, пока он в той же комнате, что и вы. А своему знакомому вы можете позвонить, где бы он ни был.
Вернёмся к нашей сломанной функции dollars_to_rubles() и починим её. Сначала поменяем имя глобальной переменной на более говорящее, назовём её budget_rubles:
budget_rubles = 1200
budget_dollars = 65
rubles_for_dollar = 67.01
def dollars_to_rubles(dollars):
rubls = dollars * rubles_for_dollar
return rubles
total = budget_rubles + dollars_to_rubles(budget_dollars)
print("Суммарный бюджет: {:.2f} млн ₽".format(total))
Traceback (most recent call last):
File "main.py", line 10, in <module>
total = budget_rubles + dollars_to_rubles(budget_dollars)
File "main.py", line 8, in dollars_to_rubles
return rubles
NameError: name 'rubles' is not defined
Теперь Python отловил наш недосмотр и сообщает о нём. Это полезно, потому что облегчает нам поиск ошибок. Последуем совету Python и поправим локальную переменную:
budget_rubles = 1200
budget_dollars = 65
rubles_for_dollar = 67.01
def dollars_to_rubles(dollars):
rubles = dollars * rubles_for_dollar
return rubles
total = budget_rubles + dollars_to_rubles(budget_dollars)
print("Суммарный бюджет: {:.2f} млн ₽".format(total))
Суммарный бюджет: 5555.65 млн ₽
Функция dollars_to_rubles() использует глобальную переменную rubles_for_dollar. Так делать не стоит — лучше, чтобы функция работала только со своими, локальными, переменными. Иначе:
Сложно будет перенести функцию в другую программу: чтобы всё работало, придётся заодно искать и переносить глобальные переменные;
Сложно будет читать код — придётся то и дело переключаться с функции на поиск глобальной переменной в коде и обратно.
Исключение — глобальные переменные, чьё значение в коде не меняется. Такие переменные называют константами. Внимание: для Python это обычные глобальные переменные. Просто разработчики договорились, что если переменная не меняет своего значения нигде в коде, ей дают название из прописных букв. Так при чтении кода легко отличать переменные от констант. А ещё так вы гарантированно не назовёте одинаково локальную переменную и константу.
RUBLES_FOR_DOLLAR = 67.01
budget_rubles = 1200
budget_dollars = 65
def dollars_to_rubles(dollars):
rubles = dollars * RUBLES_FOR_DOLLAR
return rubles
total = budget_rubles + dollars_to_rubles(budget_dollars)
print("Суммарный бюджет: {:.2f} млн ₽".format(total))
Суммарный бюджет: 5555.65 млн ₽
Рекомендуем объявлять константы в самом начале кода программы — так их будет проще искать. Опытные разработчики хранят в константах все числовые значения, даже очевидные, вроде количества минут в часах. Это делает код понятнее.
TASK
Создайте функцию minutes_to_hours(): она должна переводить длительность фильма из минут в часы. Пусть на вход функция принимает длительность в минутах, а возвращает — в часах. Количество минут в часах запишите в константу MINUTES_IN_HOUR.
SOLUTION
# создайте константу MINUTES_IN_HOUR
MINUTES_IN_HOUR = 60
def minutes_to_hours(minutes):
length_in_mins = minutes/MINUTES_IN_HOUR
return length_in_mins
print('Длина фильма "Форма воды": {:.2f} ч.'.format(minutes_to_hours(123)))
Даже если вы не планируете переиспользовать кусок кода, его лучше заключить в функцию. Так вся программа оказывается разбита на именованные блоки, и в ней легко ориентироваться.
Вооружившись этим знанием, вернёмся к нашим фильмам.
Одна из важнейших коммерческих характеристик кинокартины — её окупаемость, или ROI. Окупаемость показывает, какую прибыль принёс каждый инвестированный доллар. Вычисляется ROI по формуле:
ROI = (СБОРЫ – БЮДЖЕТ) / БЮДЖЕТ
Напишем функцию, чтобы посчитать ROI для каждого оскаровского фильма:
# англ. add ROI, "добавить ROI"
def add_roi(data):
for i in range(len(data)):
budget = data[i][5]
gross = data[i][6]
roi = (gross - budget) / budget
data[i].append(roi)
Теперь применим нашу функцию и поймём, какие фильмы оказались самыми доходными:
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
add_roi(oscar_data)
# индекс нового столбца равен 7
oscar_data.sort(key=lambda row: row[7], reverse=True)
print('Название | ROI ')
print('------------------------------------------')
for row in oscar_data[:5]:
print('{: <35} | {: >4.1f}'.format(row[0], row[7]))
Название | ROI
------------------------------------------
Лунный свет | 42.4
Король говорит! | 26.6
Миллионер из трущоб | 24.2
Красота по-американски | 22.8
Шофёр мисс Дэйзи | 18.4
Как видите, лидеры по доходности совсем не те, что по сборам.
TASK
Посчитаем стоимость 1 минуты каждого фильма. Напишите для этого функцию add_price_per_minute(): посчитанное значение она должна добавлять в новый столбец.
На вход функция пусть принимает 1 аргумент — таблицу с данными. Эту таблицу функции предстоит изменить. Код для вывода на экран мы уже написали. Вот формула для подсчёта:
СТОИМОСТЬ_МИНУТЫ = БЮДЖЕТ / ДЛИТЕЛЬНОСТЬ
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def add_price_per_minute(data):
for i in range(len(data)):
length=data[i][3]
budget=data[i][5]
price_per_minute=budget/length
data[i].append(price_per_minute)
add_price_per_minute(oscar_data)
# индекс нового столбца равен 7
oscar_data.sort(key=lambda row: row[7], reverse=True)
print('Название | Цена за минуту, млн $ |')
print('-------------------------------------------------------------')
for row in oscar_data[:5]:
print('{: <35} | {: >21.2f} |'.format(row[0], row[7]))
Мы хотели увидеть, как меняются вкусы Киноакадемии. Для такого анализа нужно научить Python различать новые и старые фильмы.
Тут на помощь приходит условный оператор. Он позволяет создавать «развилки»: то есть задавать условие и выполнять один код, если оно выполняется, и другой — в противном случае.
Напишем функцию для проверки, получил ли фильм «Оскар» в течение последних 10 лет:
# функция
def check_if_recent(year):
if year < 2008:
print('Фильм был снят давно')
else:
print('Фильм свежий')
# примеры использования
print('Бёрдмэн')
check_if_recent(2014)
print('Титаник')
check_if_recent(1997)
Бёрдмэн
Фильм свежий.
Титаник
Фильм был снят давно.
Ключевые слова if (англ. if, «если») и else (англ. else, «иначе») задают условный оператор. Если условие выполнено, Python исполнит один код, а если нет — другой. На схеме изображён синтаксис условного оператора:
image
Для Python условный оператор — это развилка, на которой нужно принять решение, какой код исполнять. При каждом вызове функции check_if_recent() Python будет попадать на эту развилку и принимать решение.
image
Знак < в нашем условии соответствует математическому знаку <. В таблице приведено соответствие других математических знаков:
МАТЕМАТИЧЕСКИЙ ЗНАК ЗНАК В PYTHON ОПИСАНИЕ
⩽ <= меньше или равно
⩾ >= больше или равно
< < строго меньше
> > строго больше
= == в точности равно
≠ != не равно в точности
Чтобы запомнить, как правильно пишется: <= или =<, обратите внимание, что порядок такой же, как в описании: «меньше или равно», а не «равно или меньше».
TASK
Напишите функцию check_if_long(), которая будет определять, длинный фильм или нет. Фильмы, идущие меньше двух часов будем называть короткими, а остальные — длинными.
Функция должна принимать на вход длину фильма и печатать на экране:
Фильм длинный.
или
Фильм короткий.
SOLUTION
def check_if_long(length):
if length > 120:
print('Фильм длинный.')
else:
print('Фильм короткий.')
print('Артист')
check_if_long(96)
print('Гладиатор')
check_if_long(155)
Условный оператор открывает огромное поле возможностей. Например, он поможет нам фильтровать таблицы: то есть выкидывать и оставлять элементы по какому-то правилу.
Напишем функцию, чтобы отфильтровать таблицу по году. Она будет принимать как аргумент год вручения премии, и возвращать новую таблицу с фильмами, получившими награду в этом году и позже. Например, если указан 2010 год, то должны остаться только фильмы с 2010 по 2017 год.
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
# англ. filter after, "отобрать всё после"
def filter_after(data, year_threshold):
# создаём таблицу как список списков – пока пустой
result = []
for row in data:
year = row[1]
# Для оператора if можно не указывать блок else, если
# в нём ничего нет.
if year >= year_threshold:
# добавляем в таблицу строку, подходящую под условие
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
# мы не меняем исходную таблицу, а сохраняем в переменную новую
filtered_data = filter_after(oscar_data, 2010)
print_table(filtered_data)
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Форма воды | 2017 | 6.91 | 123 | 19.4 | 195.2 |
Лунный свет | 2016 | 6.15 | 110 | 1.5 | 65.0 |
В центре внимания | 2015 | 7.49 | 129 | 20.0 | 88.3 |
Бёрдмэн | 2014 | 7.60 | 119 | 18.0 | 103.2 |
12 лет рабства | 2013 | 7.71 | 133 | 20.0 | 178.4 |
Операция "Арго" | 2012 | 7.52 | 120 | 44.5 | 232.3 |
Артист | 2011 | 7.94 | 96 | 15.0 | 133.4 |
Король говорит! | 2010 | 7.98 | 118 | 15.0 | 414.2 |
TASK_1_2
Отфильтруйте таблицу, оставив в ней фильмы от 2000 года и новее. Затем отсортируйте её по сборам по убыванию и напечатайте на экране топ-5 результатов.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_after(data, year_threshold):
result = []
for row in data:
year = row[1]
if year >= year_threshold:
result.append(row)
return result
def print_top5_by_column(data, column, reverse):
data.sort(key=lambda row: row[column], reverse=reverse)
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_after(oscar_data, 2000)
print_top5_by_column(filtered_data, 6, True)
TASK_2_2
Напишите функцию фильтрации фильмов по длине. Она должна отсеивать все фильмы, длиннее времени, полученного на вход.
Функция должна получать на вход два аргумента: таблицу и время для фильтрации. Она должна возвращать новую таблицу и не менять старую.
Оставьте в таблице фильмы не длиннее двух часов, и отсортируйте её по сборам. Напечатайте топ-5 элементов полученной таблицы на экране.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_not_longer_than(data, length_threshold):
result=[]
for row in data:
length=row[3]
if length <=length_threshold:
result.append(row)
return result
def print_top5_by_column(data, column, reverse):
data.sort(key=lambda row: row[column], reverse=reverse)
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data[:5]:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_not_longer_than(oscar_data, 120)
print_top5_by_column(filtered_data,6,True)
Поле «Жанр» в нашей таблице имеет тип list. Давайте разберёмся, как фильтровать таблицу по нему.
Дело в том, что поле с типом list содержит несколько значений, а значит, математические проверки не пройдут. Для такого случая в Python есть специальный оператор: in:
print('драма' in ['фантастика', 'драма'])
print('комедия' in ['драма', 'криминал', 'история'])
True
False
Такую конструкцию нужно читать: “элемент «драма» есть в списке: «фантастика», «драма»”.
Это утверждение может быть истинным или ложным, то есть — принимать значение True или False. Таким образом, оператор in удобен в условных конструкциях:
birdman_genres = ['драма', 'комедия']
if 'криминал' in birdman_genres:
print('Фильм "Бёрдмэн" содержит жанр "криминал"')
else:
print('Фильм "Бёрдмэн" не содержит жанр "криминал"')
Фильм "Бёрдмэн" не содержит жанр "криминал"
TASK 1_2
Отфильтруем же таблицу по жанру! Для этой цели напишите функцию filter_by_genre(). Она должна иметь два аргумента: таблицу с данными и название жанра. А возвращать — новую таблицу с фильмами переданного жанра.
Как опишете логику, вызывайте новоиспечённую функцию, чтобы найти все мелодрамы.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_by_genre(data, genre):
result=[]
for row in data:
genres=row[4]
if genre in genres:
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_by_genre(oscar_data,'мелодрама')
print_table(filtered_data)
TASK 2_2
Одни жанры встречаются чаще других. Давайте найдём самые популярные. Создайте таблицу и сохраните её в переменной genres_counts. Она должна состоять из двух столбцов: «название жанра» и «количество фильмов с ним».
Все жанры мы собрали в переменной all_genres. Наполните таблицу данными. Отсортируйте столбец «количество» по убыванию. Мы уже написали код для вывода в таком формате:
Жанр | Количество
------------------------
... | ...
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
# функция для фильтрации таблицы по жанрам
def filter_by_genre(data, genre):
result = []
for row in data:
genres = row[4]
if genre in genres:
result.append(row)
return result
all_genres = [
'фантастика', 'драма', 'криминал', 'история', 'комедия', 'биография',
'триллер', 'военный', 'мелодрама', 'боевик', 'приключения', 'вестерн',
'детектив', 'ужасы'
]
genres_counts = []
# В цикле заполняется таблица genres_counts
for genre in all_genres:
# отфильтруйте таблицу по жанру genre
# используйте для этого функцию filter_by_genre()
filtered_data = filter_by_genre(oscar_data, genre)
# подсчитайте длину отфильтрованной таблицы
# используйте для этого функцию len()
count = len(filtered_data)
# добавьте название жанра и результат подсчёта в таблицу
# используйте для этого функцию append()
genres_counts.append([genre, count])
# отсортируйте таблицу по убыванию количества
# используйте для этого функцию sort()
# < напишите код здесь >
genres_counts.sort(key=lambda row: row[1],reverse=True)
print('Жанр | Количество')
print('------------------------')
for row in genres_counts:
genre = row[0]
count = row[1]
print('{: <11} | {: >10}'.format(genre, count))
Мы долго писали функции, настало время вызвать их. Python позволяет выпустить целую очередь функций в одной программе.
В прошлом уроке мы получили такой результат:
Жанр | Количество
------------------------
драма | 29
история | 7
мелодрама | 7
криминал | 6
биография | 6
триллер | 6
комедия | 4
военный | 3
приключения | 3
вестерн | 2
фантастика | 1
боевик | 1
детектив | 1
ужасы | 1
Для анализа интересны только 5 «средних» жанров: история, мелодрама, криминал, биография и триллер. Остальные редки или встречаются везде. Установим, какие параметры зависят от жанра фильма.
У нас есть функции, добавляющие дополнительные столбцы — ROI и бюджет одной минуты. Можно применить их к исходной таблице, чтобы потом исследовать жанры.
TASK
Добавьте вызовы функций add_roi() , затем add_price_per_minute() . Обеим передайте как параметр исходную таблицу oscar_data. Потом рассчитайте по каждому жанру средние величины: рейтинг, длину, ROI и бюджет минуты. Для этого воспользуйтесь уже готовой функцией column_mean().
Сведите информацию в такую таблицу:
Жанр | Рейтинг | Длина | ROI | Бюджет за минуту
-------------------------------------------------------
история | ... | ... | ... | ...
...
Сохраните её в переменной genres_means и выведите на экран. Числа печатайте с двумя знаками после запятой и выравнивайте по правому краю, а названия — по левому. В прекоде вывод уже описан.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_by_genre(data, genre):
result = []
for row in data:
genres = row[4]
if genre in genres:
result.append(row)
return result
def column_sum(data, column):
result = 0
for row in data:
result += row[column]
return result
def column_mean(data, column):
total = column_sum(data, column)
mean = total / len(data)
return mean
def add_roi(data):
for i in range(len(data)):
budget = data[i][5]
gross = data[i][6]
roi = (gross - budget) / budget
data[i].append(roi)
def add_price_per_minute(data):
for i in range(len(data)):
length = data[i][3]
budget = data[i][5]
price_per_minute = budget / length
data[i].append(price_per_minute)
# переменная с выбранными жанрами (англ. selected genres, "избранные жанры")
selected_genres = ['история', 'мелодрама', 'криминал', 'биография', 'триллер']
# добавьте в таблицу столбцы с ROI и стоимостью одной минуты фильма
# воспользуйтесь для этого функциями add_roi() и add_price_per_minute()
add_roi(oscar_data)
add_price_per_minute(oscar_data)
genres_means = []
for genre in selected_genres:
# отфильтруйте таблицу по жанру
filt_data = filter_by_genre(oscar_data, genre)
# посчитайте средние значения по отфильтрованной таблице
# средняя оценка (индекс столбца 2)
mean_score = column_mean(filt_data, 2)
# средняя длина (индекс столбца 3)
mean_length = column_mean(filt_data, 3)
# среднее значение ROI (индекс столбца 7)
mean_roi = column_mean(filt_data, 7)
# средняя цена за минуту (индекс столбца 8)
mean_ppm = column_mean(filt_data, 8)
genres_means.append([genre, mean_score, mean_length, mean_roi, mean_ppm])
print('Жанр | Рейтинг | Длина | ROI | Бюджет за минуту')
print('-------------------------------------------------------')
for row in genres_means:
print('{: <9} | {: >7.2f} | {: >5.2f} | {: >5.2f} | {: >16.2f}'.format(
row[0], row[1], row[2], row[3], row[4]))
Мы получили вот такой результат:
Жанр | Рейтинг | Длина | ROI | Бюджет за минуту
-------------------------------------------------------
история | 7.86 | 143.14 | 9.48 | 0.18
мелодрама | 8.12 | 137.86 | 10.84 | 0.36
криминал | 7.93 | 122.83 | 7.47 | 0.26
биография | 8.14 | 146.50 | 9.78 | 0.27
триллер | 7.87 | 123.50 | 7.01 | 0.25
Какие выводы можно сделать из таблицы:
Самые дорогие и прибыльные фильмы — мелодрамы. В них снимаются самые дорогие звёзды — это одновременно объясняет и высокий бюджет, и прибыльность фильмов. Ещё большой вклад в общую картину внёс фильм «Титаник» с монструозно высокими бюджетом и сборами.
Криминальные фильмы и триллеры наименее длинные и прибыльные. Вероятно, невозможно удерживать накал слишком долго: у человека есть физиологические ограничения. При этом высокое напряжение — удовольствие на любителя, и некоторые люди просто не смотрят такие фильмы.
Исторические фильмы — самые дешёвые. Быть может, потому, что исторический фильм всегда найдёт своего зрителя. Ведь знаменитости из прошлого сами по себе — бренд; можно сэкономить на актёрском составе и музыке.
Каждая из гипотез тянет на отдельное исследование. Возможно, когда-нибудь мы к ним вернёмся. А сейчас продолжим изучать вкусы киноакадемии.
В нашем списке есть только один фильм без жанра «драма». Давайте найдём его. В этом нам поможет оператор not. Оператор not переворачивает любое условие с ног на голову — меняет True на False и наоборот:
print(not True)
print(not False)
False
True
Например, можно переписать функцию для проверки, является ли фильм свежим (снят после 2007):
def check_if_recent(year):
if not year > 2007:
print('Фильм был снят давно.')
else:
print('Фильм свежий.')
TASK
Допишите функцию filter_without_genre(). Она должна выкидывать из таблицы все фильмы заданного жанра. Аргументы этой функции: таблица с фильмами и жанр, который нужно исключить. Исходные данные менять не надо — пусть функция возвращает новую, очищенную таблицу.
Вызовите написанную функцию, чтобы найти в таблице все фильмы без жанра «драма».
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_without_genre(data, genre):
result = []
for row in data:
genres = row[4]
if genre not in genres:
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_without_genre(oscar_data, 'драма')
print_table(filtered_data)
Для построения более сложных условий в Python есть ещё два оператора: and и or.
Оператор and объединяет два условия в одно. Такое составное условие возвращает True только тогда, когда выполнены оба простых условия:
print(True and True)
print(True and False)
print(False and True)
print(False and False)
True
False
False
False
Воспользуемся этим оператором, чтобы найти в таблице все исторические фильмы новее 2000 года:
if year > 2000 and 'история' in genres:
...
Полный код:
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_new_historic(data):
result = []
for row in data:
year = row[1]
genres = row[4]
if year > 2000 and 'история' in genres:
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_new_historic(oscar_data)
print_table(filtered_data)
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
В центре внимания | 2015 | 7.49 | 129 | 20.0 | 88.3 |
12 лет рабства | 2013 | 7.71 | 133 | 20.0 | 178.4 |
Король говорит! | 2010 | 7.98 | 118 | 15.0 | 414.2 |
Повелитель бури | 2008 | 7.30 | 126 | 15.0 | 49.2 |
Оператор or тоже объединяет два условия в одно. Такое составное условие возвращает True, если выполнено хотя бы одно из простых условий:
print(True or True)
print(True or False)
print(False or True)
print(False or False)
True
True
True
False
Давайте найдём в таблице все фильмы жанров «фэнтези» и «фантастика»:
if 'фантастика' in genres or 'фэнтези' in genres:
...
Полный код:
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_fantastic(data):
result = []
for row in data:
genres = row[4]
if 'фантастика' in genres or 'фэнтези' in genres:
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_fantastic(oscar_data)
print_table(filtered_data)
Название | Год | Рейтинг | Длина | Бюджет | Сборы |
--------------------------------------------------------------------------------
Форма воды | 2017 | 6.91 | 123 | 19.4 | 195.2 |
Властелин колец: Возвращение Короля | 2003 | 8.62 | 201 | 94.0 | 1119.1 |
TASK_1_2
Напишите функцию filter_suspense(), которая находит фильмы самых напряжённых жанров: «триллер» и «ужасы». Функция должна принимать как аргумент исходную таблицу и, не меняя её, возвращать отфильтрованную.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_suspense(data):
result = []
for row in data:
genres = row[4]
if 'триллер' in genres or 'ужасы' in genres:
result.append(row)
return result
def print_table(data):
print('Название | Год |A Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_suspense(oscar_data)
print_table(filtered_data)
TASK_2_2
Для анализа фильмов по годам нам нужно научиться выделять из таблицы диапазоны: например с 2000 по 2010 год. Напишите функцию filter_first_decade(), которая фильтрует таблицу по этому условию. Функция должна получать на вход исходную таблицу и, не меняя её, возвращать отфильтрованную.
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_first_decade(data):
result = []
for row in data:
year = row[1]
if year > 1999 and year < 2011:
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_first_decade(oscar_data)
print_table(filtered_data)
SOLUTION
Прежде чем перейти к анализу фильмов по годам, рассмотрим несколько удобных сокращений.
Напишем функцию, которая будет относить фильм к одной из трёх категорий: короткий, средний или длинный.
def length_category(length):
if length > 130:
return 'длинный'
else:
if length <= 130 and length > 120:
return 'средний'
else:
return 'короткий'
В этом коде есть вложенное условие. Избавиться от него можно ключевым словом elif (сокр. англ. else if, «иначе если»):
def length_category(length):
if length > 130:
return 'длинный'
elif length <= 130 and length > 120:
return 'средний'
else:
return 'короткий'
Условие
length <= 130 and length > 120
также можно сократить:
120 < length <= 130
В итоге функция выглядит так:
def length_category(length):
if length > 130:
return 'длинный'
elif 120 < length <= 130:
return 'средний'
else:
return 'короткий'
TASK
Напишите функцию filter_by_year() для отбора фильмов по годам. Она должна возвращать таблицу с фильмами, снятыми в определённый период.
На вход функция принимает три аргумента: данные о фильмах и границы периода. Фильмы, снятые в последний год промежутка, должны быть отсеяны, а в первый — включены (это требуется, чтобы промежутки не накладывались друг на друга). Пользуйтесь сокращённой записью для условий.
Код для вывода таблицы на экран мы уже написали.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_by_year(data, begin, end):
result=[]
for row in data:
year=row[1]
if begin<= year<end:
result.append(row)
return result
def print_table(data):
print('Название | Год | Рейтинг | Длина | Бюджет | Сборы |')
print('--------------------------------------------------------------------------------')
for row in data:
print('{: <35} | {} | {: >7.2f} | {: >5} | {: >6.1f} | {: >6.1f} |'.format(
row[0], row[1], row[2], row[3], row[5], row[6]))
filtered_data = filter_by_year(oscar_data, 2000, 2010)
print_table(filtered_data)
Теперь соберём всё вместе и исследуем динамику разных величин по годам.
TASK
Поделим 30 лет на 3 периода по 10 лет. Для фильмов из каждого диапазона посчитаем средние рейтинг, длину, стоимость съёмок одной минуты и сборы. Допишите код, чтобы создать таблицу с этой информацией и вывести её на экран.
SOLUTION
oscar_data = [
['Форма воды', 2017, 6.914, 123, ['фантастика', 'драма'], 19.4, 195.243464],
['Лунный свет', 2016, 6.151, 110, ['драма'], 1.5, 65.046687],
['В центре внимания', 2015, 7.489, 129, ['драма', 'криминал', 'история'], 20.0, 88.346473],
['Бёрдмэн', 2014, 7.604, 119, ['драма', 'комедия'], 18.0, 103.215094],
['12 лет рабства', 2013, 7.71, 133, ['драма', 'биография', 'история'], 20.0, 178.371993],
['Операция "Арго"', 2012, 7.517, 120, ['триллер', 'драма', 'биография'], 44.5, 232.324128],
['Артист', 2011, 7.942, 96, ['драма', 'мелодрама', 'комедия'], 15.0, 133.432856],
['Король говорит!', 2010, 7.977, 118, ['драма', 'биография', 'история'], 15.0, 414.211549],
['Повелитель бури', 2008, 7.298, 126, ['триллер', 'драма', 'военный', 'история'], 15.0, 49.230772],
['Миллионер из трущоб', 2008, 7.724, 120, ['драма', 'мелодрама'], 15.0, 377.910544],
['Старикам тут не место', 2007, 7.726, 122, ['триллер', 'драма', 'криминал'], 25.0, 171.627166],
['Отступники', 2006, 8.456, 151, ['триллер', 'драма', 'криминал'], 90.0, 289.847354],
['Столкновение', 2004, 7.896, 108, ['триллер', 'драма', 'криминал'], 6.5, 98.410061],
['Малышка на миллион', 2004, 8.075, 132, ['драма', 'спорт'], 30.0, 216.763646],
['Властелин колец: Возвращение Короля', 2003, 8.617, 201, ['фэнтези', 'драма', 'приключения'], 94.0, 1119.110941],
['Чикаго', 2002, 7.669, 113, ['мюзикл', 'комедия', 'криминал'], 45.0, 306.776732],
['Игры разума', 2001, 8.557, 135, ['драма', 'биография', 'мелодрама'], 58.0, 313.542341],
['Гладиатор', 2000, 8.585, 155, ['боевик', 'драма', 'приключения'], 103.0, 457.640427],
['Красота по-американски', 1999, 7.965, 122, ['драма'], 15.0, 356.296601],
['Влюбленный Шекспир', 1998, 7.452, 123, ['драма', 'мелодрама', 'комедия', 'история'], 25.0, 289.317794],
['Титаник', 1997, 8.369, 194, ['драма', 'мелодрама'], 200.0, 2185.372302],
['Английский пациент', 1996, 7.849, 155, ['драма', 'мелодрама', 'военный'], 27.0, 231.976425],
['Храброе сердце', 1995, 8.283, 178, ['драма', 'военный', 'биография', 'история'], 72.0, 210.409945],
['Форрест Гамп', 1994, 8.915, 142, ['драма', 'мелодрама'], 55.0, 677.386686],
['Список Шиндлера', 1993, 8.819, 195, ['драма', 'биография', 'история'], 22.0, 321.265768],
['Непрощенный', 1992, 7.858, 131, ['драма', 'вестерн'], 14.4, 159.157447],
['Молчание ягнят', 1990, 8.335, 114, ['триллер', 'криминал', 'детектив', 'драма', 'ужасы'], 19.0, 272.742922],
['Танцующий с волками', 1990, 8.112, 181, ['драма', 'приключения', 'вестерн'], 22.0, 424.208848],
['Шофёр мисс Дэйзи', 1989, 7.645, 99, ['драма'], 7.5, 145.793296],
['Человек дождя', 1988, 8.25, 133, ['драма'], 25.0, 354.825435],
]
def filter_by_year(data, begin, end):
result = []
for row in data:
year = row[1]
if begin <= year < end:
result.append(row)
return result
def column_sum(data, column):
result = 0
for row in data:
result += row[column]
return result
def column_mean(data, column):
total = column_sum(data, column)
mean = total / len(data)
return mean
def add_price_per_minute(data):
for i in range(len(data)):
length = data[i][3]
budget = data[i][5]
price_per_minute = budget / length
data[i].append(price_per_minute)
add_price_per_minute(oscar_data)
years = [[1988, 1998], [1998, 2008], [2008, 2018]]
rows = []
for begin_end in years:
# извлекаем начало и конец промежутка
begin = begin_end[0]
end = begin_end[1]
# создаем текстовую запись промежутка
name = '{}-{}'.format(begin, end)
# отфильтруйте таблицу по промежутку
filt_data = filter_by_year(oscar_data, begin, end)
# вычислите средние значения
mean_score = column_mean(filt_data, 2)
mean_length = column_mean(filt_data, 3)
mean_ppm = column_mean(filt_data, 7)
mean_gross = column_mean(filt_data, 6)
# добавьте строку в новую таблицу
rows.append([name, mean_score, mean_length, mean_ppm, mean_gross])
print('Годы | Рейтинг | Длина | Бюджет за минуту | Сборы ')
print('--------------------------------------------------------')
for row in rows:
print('{: <9} | {: >7.2f} | {: >5.2f} | {: >16.2f} | {: >6.2f}'.format(
row[0], row[1], row[2], row[3], row[4]))
Получили такую таблицу:
Годы | Рейтинг | Длина | Бюджет за минуту | Сборы
--------------------------------------------------------
1988-1998 | 8.24 | 152.20 | 0.28 | 498.31
1998-2008 | 8.10 | 136.20 | 0.34 | 361.93
2008-2018 | 7.43 | 119.40 | 0.15 | 183.73
Из таблицы мы можем заключить:
фильмы становятся короче;
дешевле;
их зрительский рейтинг падает;
а сборы уменьшаются.
Первый вывод, который напрашивается: фильмы становятся хуже. Но такое рассуждение было бы огульным: мы не учитываем контекст времени и динамику рынка кинематографа. Более точная гипотеза — вкусы киноакадемии уходят от коммерчески успешного кино в сторону «фестивального» кино.
Выводы из данных
Оскароносные фильмы становятся короче, дешевле и при этом у них понижается пользовательский рейтинг и сборы. Вкусы киноакадемии всё больше двигаются в сторону искусства и всё дальше уходят от кино как бизнеса.
Мелодрама — самый дорогой и прибыльный жанр. Это связано с его популярностью и высокими гонорарами актёров. Также большой вклад внёс фильм «Титаник» с большим бюджетом и сборами.
Криминальные фильмы и триллеры самые короткие и приносят кинокомпаниям меньше всего денег. Вероятно, причина этого – высокое напряжение, которое тяжело долго выдерживать и не всем по нраву.
Что дальше
Первая бизнес-задача, похожая на реальную: анализ данных Яндекс.Музыки и оценка результатов поставленного на этом сервисе эксперимента. Вы познакомитесь с библиотекой Pandas, которая позволит перейти от учебных табличек к реальным выборкам.
Забери с собой
Чтобы ничего не забыть, скачайте шпаргалку
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment