Применение функций
Функции в Python вызываются путём помещения параметров в круглые скобки после имени функции. Так вызываются все определённые функции. Существует также особый вид функций — методы, которые похожи на обычные функции, но вызываются через точку после объекта, например, some_table.sort(some_label). Определённые вами функции всегда будут использовать имя функции и передавать ей все параметры при вызове.
Применение функции к столбцу таблицы
Мы уже видели множество примеров применения функций к существующему столбцу или другому массиву для создания нового столбца таблицы. Все эти функции принимают массив в качестве параметра. Однако часто мы хотим преобразовать элементы столбца, не передавая массив в функцию. Например, функция может принимать только число в качестве аргумента, как в примере ниже:
def cut_off_at_100(x):
"""The smaller of x and 100"""
return min(x, 100)
cut_off_at_100(17)
17
cut_off_at_100(117)
100
cut_off_at_100(100)
100
Если параметр меньше или равен 100, функция cut_off_at_100 просто возвращает его. Если параметр больше 100, она возвращает 100.
В примере с данными переписи населения переменная AGE имеет значение 100, что означает «100 лет и старше». Именно это делает функция cut_off_at_100.
Чтобы применить эту функцию сразу ко многим возрастам, нам нужно иметь возможность ссылаться на саму функцию, а не вызывать её напрямую. Аналогично, мы можем попросить повара приготовить торт по рецепту и попросить его испечь 6 тортов. В этом случае мы не будем сами печь торты, используя рецепт, наша роль заключается в том, чтобы передать повару рецепт. Точно так же мы можем попросить таблицу применить функцию cut_off_at_100 к 6 различным числам в столбце.
Сначала мы создаём таблицу с одним столбцом для людей и одним столбцом для их возраста. Например, C — 52 года.
ages = Table().with_columns(
'Person', make_array('A', 'B', 'C', 'D', 'E', 'F'),
'Age', make_array(17, 117, 52, 100, 6, 101)
)
ages
Person | Age |
---|---|
A | 17 |
B | 117 |
C | 52 |
D | 100 |
E | 6 |
F | 101 |
Для ограничения возраста до 100 лет мы будем использовать новый метод Table. Метод apply применяет функцию к каждому элементу столбца и формирует новый массив возвращаемых значений. Чтобы указать функцию, которую нужно вызвать, просто назовите её (без кавычек или скобок). Имя столбца входных значений должно быть строкой, заключённой в кавычки.
ages.apply(cut_off_at_100, 'Age')
array([ 17, 100, 52, 100, 6, 100])
Здесь мы применяем функцию cut_off_at_100 к столбцу Age таблицы ages. Результатом является массив возвращаемых значений функции. Например, 17 остаётся 17, 117 становится 100, 52 остаётся 52 и т. д.
Этот массив имеет ту же длину, что и исходный столбец Age таблицы, и может использоваться как значения нового столбца Cut Off Age, который существует вместе с существующими столбцами Person и Age.
ages.with_column(
'Cut Off Age', ages.apply(cut_off_at_100, 'Age')
)
Person | Age | Cut Off Age |
---|---|---|
A | 17 | 17 |
B | 117 | 100 |
C | 52 | 52 |
D | 100 | 100 |
E | 6 | 6 |
F | 101 | 100 |
В Python каждая функция (включая cut_off_at_100) также является значением. Это помогает нам снова рассмотреть рецепты. Рецепт торта — это реальная вещь, отличная от торта или ингредиентов, вы можете дать ему имя, например «Рецепт торта Ани». Когда мы определяем cut_off_at_100 с помощью оператора def, мы фактически делаем две вещи: мы создаём функцию для ограничения чисел до 100 и даём ей имя cut_off_at_100.
Мы можем ссылаться на любую функцию, написав её имя без фактического вызова с использованием скобок или параметров. Когда мы вызываем apply выше, мы это сделали. Когда мы пишем имя функции в виде строки в ячейке, Python генерирует текстовое представление функции, похожее на печать числа или строкового значения.
cut_off_at_100
<function __main__.cut_off_at_100>
Обратите внимание, что мы не использовали кавычки (это просто текст) или cut_off_at_100() (это вызов функции, и он недействителен). Мы просто написали cut_off_at_100 для ссылки на эту функцию.
Подобно тому, как мы можем давать новые имена другим значениям, мы также можем давать функции новые имена. Например, предположим, что мы хотим назвать нашу функцию cut_off вместо cut_off_at_100. Мы можем сделать это следующим образом:
cut_off = cut_off_at_100
Теперь cut_off — это функция с тем же именем, что и cut_off_at_100. Поэтому вывод должен быть таким же.
cut_off
<function __main__.cut_off_at_100>
Давайте посмотрим на другое применение apply.
Данные часто используются для прогнозирования будущего. Если мы пытаемся предсказать результат конкретного человека, например, как он отреагирует на лечение или купит ли он продукт, то естественно основывать прогноз на результатах других похожих людей.
Чарльз Дарвин (Charles Darwin) был вдохновлён этой идеей, когда пытался понять, как физические характеристики передаются по наследству. Его старший брат Фрэнсис Гальтон (Sir Francis Galton) был пионером в использовании этого подхода для прогнозирования на основе числовых данных. Он тщательно собирал данные о физических характеристиках, таких как рост родителей и их взрослых детей. Каждая строка представляет одного взрослого ребёнка. Переменные включают код семьи, рост отца и матери в дюймах, средний рост обоих родителей, количество детей в семье, номер рождения ребёнка, пол и рост ребёнка.
[1] Гальтон при вычислении среднего роста мужчин и женщин сначала умножал рост женщин на 1,08. Для обсуждения этого вопроса см. Chance, журнал, издаваемый Американской статистической ассоциацией.
# Galton's data on heights of parents and their adult children
galton = Table.read_table('galton.csv')
galton
family | father | mother | midparentHeight | children | childNum | gender | childHeight |
---|---|---|---|---|---|---|---|
1 | 78.5 | 67 | 75.43 | 4 | 1 | male | 73.2 |
1 | 78.5 | 67 | 75.43 | 4 | 2 | female | 69.2 |
1 | 78.5 | 67 | 75.43 | 4 | 3 | female | 69 |
1 | 78.5 | 67 | 75.43 | 4 | 4 | female | 69 Перевод текста на русский язык: |
Есть два разных типа: шоколад и клубника. Вызов функции group создаст счётчик для каждой категории. Этот столбец по умолчанию называется count и содержит количество строк в каждой категории.
Обратите внимание, что всё это можно найти в столбце Flavor. Столбец Price ещё не используется.
Но что, если мы хотим узнать общую стоимость каждого вида рожка? Это работа второго параметра функции group.
Второй необязательный параметр функции group — это функция, которая используется для объединения значений других столбцов всех этих строк. Например, sum будет накапливать цену всех совпадающих строк для каждой категории. В этом результате каждая уникальная строка в сгруппированном столбце является строкой, но количество столбцов такое же, как и в исходной таблице.
Чтобы найти общую стоимость каждой разновидности вкуса, мы снова вызываем group, используя Flavor в качестве первого параметра. Но на этот раз есть второй параметр: имя функции sum.
cones.group('Flavor', sum)
Flavor | Price sum |
---|---|
chocolate | 16.55 |
strawberry | 8.8 |
Для создания этой новой таблицы group уже вычислила сумму всех строк, соответствующих каждому вкусу. Три строки шоколада стоят в общей сложности $16,55 (вы можете предположить, что цены указаны в долларах). Две строки клубники стоят 8,80.
Метка нового созданного столбца «Сумма» — «Цена сумма», она создана с использованием метки столбца, к которому применяется суммирование, и добавления слова «сумма».
Поскольку group вычисляет сумму всех столбцов, кроме категории, нет необходимости указывать, какие столбцы суммировать.
Чтобы лучше понять, что делает group, вы можете заметить, что вы можете вычислить общую стоимость самостоятельно, не только мысленно, но и с помощью кода. Например, чтобы найти общую стоимость всех шоколадных рожков, вы можете начать с создания новой таблицы, содержащей только шоколадные рожки, а затем получить доступ к столбцу цен:
cones.where('Flavor', are.equal_to('chocolate')).column('Price')
array([ 4.75, 6.55, 5.25])
sum(cones.where('Flavor', are.equal_to('chocolate')).column('Price'))
16.550000000000001
Это то, что group делает для каждого отдельного значения в Flavor.
Пример: зарплаты игроков NBA
Таблица nba содержит данные о игроках NBA за 2015–2016 годы. Мы рассмотрели эти данные ранее. Напомним, зарплата указана в миллионах долларов.
nba1 = Table.read_table('nba_salaries.csv')
nba = nba1.relabeled("'15-'16 SALARY", 'SALARY')
nba
PLAYER | POSITION | TEAM | SALARY |
---|---|---|---|
Paul Millsap | PF | Atlanta Hawks | 18.6717 |
Al Horford | C | Atlanta Hawks | 12 |
Tiago Splitter | C | Atlanta Hawks | 9.75625 |
Jeff Teague | PG | Atlanta Hawks | 8 |
Kyle Korver | SG | Atlanta Hawks | 5.74648 |
Thabo Sefolosha | SF | Atlanta Hawks | 4 |
Mike Scott | PF | Atlanta Hawks | 3.33333 |
Kent Bazemore | SF | Atlanta Hawks | 2 |
Dennis Schroder | PG | Atlanta Hawks | 1.7634 |
Tim Hardaway Jr. | SG | Atlanta Hawks | 1.30452 |
(Опущено 407 строк)
(1) Сколько денег каждая команда заплатила игрокам?
Единственные задействованные столбцы — TEAM и SALARY. Нам нужно сгруппировать эти строки по TEAM, а затем сложить зарплату для каждой группы.
teams_and_money = nba.select('TEAM', 'SALARY')
teams_and_money.group('TEAM', sum)
TEAM | SALARY sum |
---|---|
Atlanta Hawks | 69.5731 |
Boston Celtics | 50.2855 |
Brooklyn Nets | 57.307 |
Charlotte Hornets | 84.1024 |
Chicago Bulls | 78.8209 |
Cleveland | Значение |
--- | |
коричневый | 0 |
светло-коричневый | 0 |
розовый | 4.75 |
Здесь group
сделал то же самое.
more_cones.group(['Flavor', 'Color'], sum)
Вкус | Цвет | Сумма |
---|---|---|
жевательная резинка | розовый | 4,75 |
шоколад | тёмно-коричневый | 10,5 |
шоколад | светло-коричневый | 4,75 |
клубника | розовый | 8,8 |
Хотя цифры в двух таблицах одинаковы, таблица, созданная с помощью pivot
, более удобна для чтения и, следовательно, более удобна для анализа. Преимущество сводной таблицы заключается в том, что она помещает значения групп в соседние столбцы, чтобы их можно было комбинировать и сравнивать.
Калифорнийский портал открытых данных является богатым источником информации о жизни в Калифорнии. Это набор данных об уровне образования и личном доходе калифорнийцев за период с 2008 по 2014 год. Данные взяты из текущего опроса американского населения, проводимого переписью населения.
Для каждого года в таблице записано количество жителей Калифорнии (Population Count
) с разбивкой по возрасту, полу, уровню образования и личному доходу. Мы рассмотрим данные только за 2014 год.
full_table = Table.read_table('educ_inc.csv')
ca_2014 = full_table.where('Year', are.equal_to('1/1/14 0:00')).where('Age', are.not_equal_to('00 to 17'))
ca_2014
Год | Возраст | Пол | Уровень образования | Личный доход | Количество жителей |
---|---|---|---|---|---|
1/1/14 0:00 | от 18 до 64 лет | женский | без аттестата о среднем образовании | H: 75 000 и выше | 2 058 |
1/1/14 0:00 | от 65 до 80+ лет | мужской | без аттестата о среднем образовании | H: 75 000 и выше | 2 153 |
1/1/14 0:00 | от 65 до 80+ лет | женский | без аттестата о среднем образовании | G: от 50 000 до 74 999 | 4 666 |
1/1/14 0:00 | от 65 до 80+ лет | женский | аттестат о среднем образовании или эквивалент | H: 75 000 и выше | 7 122 |
1/1/14 0:00 | от 65 до 80+ лет | женский | без аттестата о среднем образовании | F: от 35 000 до 49 999 | 7 261 |
1/1/14 0:00 | от 65 до 80+ лет | мужской | без аттестата о среднем образовании | G: от 50 000 до 74 999 | 8 569 |
1/1/14 0:00 | от 18 до 64 лет | женский | без аттестата о среднем образовании | G: от 50 000 до 74 999 | 14 635 |
1/1/14 0:00 | от 65 до 80+ лет | мужской | без аттестата о среднем образовании | F: от 35 000 до 49 999 | 15 212 |
1/1/14 0:00 | от 65 до 80+ лет | мужской | колледж, менее 4-х лет обучения | B: от 5 000 до 9 999 | 15 423 |
1/1/14 0:00 | от 65 до 80+ лет | женский | степень бакалавра или выше | A: от 0 до 4 999 | 15 459 |
(Опущено 117 строк)
Каждая строка в таблице соответствует группе возраста, пола, уровня образования и дохода. Всего существует 127 таких комбинаций!
В качестве первого шага хорошей идеей будет начать с одного или двух переменных. Мы сосредоточимся на одной паре: уровень образования и личный доход.
educ_inc = ca_2014.select('Educational Attainment', 'Personal Income', 'Population Count')
educ_inc
Уровень образования | Личный доход | Количество жителей |
---|---|---|
без аттестата о среднем образовании | H: 75 000 и выше | 2 058 |
без аттестата о среднем образовании | H: 75 000 и выше | 2 153 |
без аттестата о среднем образовании | G: от 50 000 до 74 999 | 4 666 |
аттестат о среднем образовании или эквивалент | H: 75 000 и выше | 7 122 |
без аттестата о среднем образовании | F: от 35 000 до 49 999 | 7 261 |
без аттестата о среднем образовании | G: от 50 000 до 74 999 | 8 569 |
без аттестата о среднем образовании | G: от 50 000 до 74 999 | 14 635 |
без аттестата о среднем образовании | F: от 35 000 до 49 999 | 15 212 |
колледж, менее 4-х лет обучения | B: от 5 000 до 9 999 | 15 423 |
степень бакалавра или выше | A: от 0 до 4 999 | 15 459 |
(Опущено 117 строк)
Сначала посмотрим на уровень образования. Эта переменная уже разделена на разные уровни дохода. Поэтому мы сгруппируем по уровню образования и сложим население каждой категории.
education = educ_inc.select('Educational Attainment', 'Population Count')
educ_totals = education.group('Educational Attainment', sum)
educ_totals
Уровень образования | Общее количество жителей |
---|---|
степень бакалавра или выше | 8 525 698 |
колледж, менее 4-х лет обучения | 7 775 497 |
аттестат о среднем образовании или эквивалент | 6 294 141 |
без аттестата о среднем образовании | 4 258 277 |
Уровень образования имеет только четыре категории. Количество слишком велико, и процентное соотношение помогает лучше понять ситуацию. Для этого мы будем использовать функцию percents
, определённую в предыдущем разделе. Она преобразует массив значений в массив процентов от общей суммы массива.
Мы теперь имеем распределение уровня образования среди взрослых жителей Калифорнии. Более 30% имеют степень бакалавра или выше, а почти 16% не имеют аттестата о среднем образовании.
educ_distribution = educ_totals.with_column(
'Population Percent', percents(educ_totals.column(1))
)
educ_distribution
Уровень образования | Общее количество жителей | Процент населения |
---|---|---|
степень бакалавра или выше | 8 525 698 | 31,75 |
колледж, менее 4-х лет обучения | 7 775 497 | 28,96 |
аттестат о среднем образовании или эквивалент | 6 294 141 | 23,44 |
без аттестата о среднем образовании | 4 258 277 | 15,86 |
Используя pivot
, мы можем получить сводную таблицу для взрослых жителей Калифорнии (таблицу подсчёта), классифицированную по уровню образования и личным доходам.
totals = educ_inc.pivot('Educational Attainment', 'Personal Income', values='Population Count', collect=sum)
totals
Личный доход | Степень бакалавра или выше | Колледж, менее 4-х лет обучения | Аттестат о среднем образовании или эквивалент | Без аттестата о среднем образовании |
---|---|---|---|---|
H: 75 000 и выше | 1 137 920 | 572 916 | 243 062 | 95 885 |
G: от 50 000 до 74 999 | 5 468 479 | 2 213 581 | 3 871 079 | 3 393 407 |
F: от 35 000 до 49 999 | 6 903 738 | 2 609 511 | 2 447 070 | 3 202 891 |
E: от 20 000 до 34 999 | 0 | 0 | 0 | 0 |
D: от 10 000 до 19 999 | 0 | 0 | 0 | 0 |
Здесь вы можете увидеть силу pivot по сравнению с другими методами. Подсчёт в каждой колонке представляет собой распределение личного дохода среди людей с определённым уровнем образования. Если перевести подсчёт в проценты, мы сможем сравнить четыре распределения.
distributions = totals.select(0).with_columns(
"Степень бакалавра или выше", percents(totals.column(1)),
'Колледж, степень менее 4 лет', percents(totals.column(2)),
'Средняя школа или эквивалент', percents(totals.column(3)),
'Отсутствие диплома о среднем образовании', percents(totals.column(4))
)
distributions
Личный доход | Степень бакалавра или выше | Колледж, степень менее 4 лет | Средняя школа или эквивалент | Отсутствие диплома о среднем образовании |
---|---|---|---|---|
A: 0–4999 | 6,75% | 12,67% | 18,46% | 28,29% |
B: 5000–9999 | 3,82% | 10,43% | 9,95% | 14,02% |
C: 10 000–14 999 | 5,31% | 10,27% | 11% | 15,61% |
D: 15 000–24 999 | 9,07% | 17,3% | 19,9% | 20,56% |
E: 25 000–34 999 | 8,14% | 14,04% | 14,76% | 10,91% |
F: 35 000–49 999 | 13,17% | 14,31% | 12,44% | 6,12% |
G: 50 000–74 999 | 18,7% | 11,37% | 8,35% | 3,11% |
H: 75 000 и более | 35,03% | 9,62% | 5,13% | 1,38% |
Сразу видно, что более 35 % людей со степенью бакалавра и выше имеют доход свыше 75 тысяч долларов, тогда как менее 10 % людей с другим уровнем образования достигают этого уровня.
На приведённой ниже гистограмме сравнивается распределение доходов взрослых людей без среднего образования в Калифорнии и распределение доходов людей со степенями бакалавра или более высокими. Различия поразительны. Существует явная положительная корреляция между уровнем образования и личным доходом.
distributions.select(0, 1, 4).barh(0)
Рисунок 7-6.
Обычно данные об одном человеке хранятся в нескольких таблицах. Например, в одном офисе университета могут быть данные о времени получения степени каждым студентом, а в другом — данные о студенческих платежах и финансовой помощи.
Объединение этих двух наборов данных может помочь получить представление о жизни студента. Если данные находятся в двух таблицах, где каждая строка соответствует одному студенту, то мы хотим объединить эти столбцы таким образом, чтобы строки оставались соответствующими друг другу, сохраняя информацию о каждом студенте в одной строке.
Давайте реализуем это на простом примере, а затем применим этот метод к большему набору данных.
Представим себе две таблицы, которые мы уже встречали ранее. Теперь предположим, что оценки за каждый вкус мороженого находятся в отдельной таблице.
cones = Table().with_columns(
'Flavor', make_array('strawberry', 'vanilla', 'chocolate', 'strawberry', 'chocolate'),
'Price', make_array(3.55, 4.75, 6.55, 5.25, 5.75)
)
cones
Вкус | Цена |
---|---|
клубничное | 3,55 |
ванильное | 4,75 |
шоколадное | 6,55 |
клубничное | 5,25 |
шоколадное | 5,75 |
ratings = Table().with_columns(
'Вид', make_array('клубничное', 'шоколадное', 'ванильное'),
'Звёзды', make_array(2,5, 3,5, 4)
)
ratings
Вид | Звёзды |
---|---|
Клубничное | 2,5 |
Шоколадное | 3,5 |
Ванильное | 4 |
Каждая таблица содержит столбец, содержащий вкусы мороженого: cones
имеет столбец Flavor
, а ratings
— столбец Kind
. Эти столбцы можно использовать для соединения двух таблиц.
Метод join
создаёт новую таблицу, в которой каждая порция мороженого из cones
дополняется информацией об оценке. Для каждой порции мороженого в cones
join
находит строку в ratings
, чей столбец Kind
соответствует вкусу мороженого в столбце Flavor
. Мы должны сообщить join
, какие столбцы использовать для сопоставления.
rated = cones.join('Flavor', ratings, 'Kind')
rated
Вкус | Цена | Звёзды |
---|---|---|
шоколадное | 6,55 | 3,5 |
шоколадное | 5,75 | 3,5 |
клубничное | 3,55 | 2,5 |
клубничное | 5,25 | 2,5 |
ванильное | 4,75 | 4 |
Теперь каждая порция мороженого имеет не только цену, но и оценку вкуса.
В общем случае использование информации из другой таблицы (например, table2
) для дополнения другой таблицы (table1
) в вызове join
выглядит следующим образом:
table1.join(table1_column_for_joining, table2, table2_column_for_joining)
Новый rated
позволяет нам вычислить соотношение цены и звёзд, которое можно рассматривать как неформальный показатель ценности. Низкие значения лучше — они означают, что вы платите меньше за каждую звезду оценки.
rated.with_column('$/Star', rated.column('Price') / rated.column('Stars')).sort(3)
Вкус | Цена | Звёзды | $/Star |
---|---|---|---|
ванильное | 4,75 | 4 | 1,1875 |
клубничное | 3,55 | 2,5 | 1,42 |
шоколадное | 5,75 | 3,5 | 1,64286 |
шоколадное | 6,55 | 3,5 | 1,87143 |
клубничное | 5,25 | 2,5 | 2,1 |
Хотя клубничное мороженое получило самые низкие оценки среди трёх вкусов, оно является самым дешёвым, поскольку стоимость каждой звезды не так высока.
Предупреждение. Порядок важен. Поскольку вторая таблица используется для дополнения первой в методе join
, важно, чтобы в первой таблице для каждой строки была только одна совпадающая строка во второй таблице. Если в первой таблице нет совпадений для какой-либо строки во второй таблице, информация может быть потеряна. Если первая таблица имеет несколько совпадений в какой-либо строке во второй таблице, join
выбирает только одно, что также приводит к потере информации.
Мы можем увидеть это в следующем примере, который пытается соединить те же две таблицы с одинаковыми столбцами, но в другом порядке. Это соединение не имеет смысла: оно пытается использовать цену для расширения каждой оценки вкуса, но согласно таблице cones
, у каждого вкуса есть более одной порции (и цены). В результате исчезают две порции. Метод join
просто находит соответствие для chocolate
в cones
и игнорирует остальные строки.
ratings.join('Kind', cones, 'Flavor')
Вид | Звёзды | Цена |
---|---|---|
шоколадное | 3,5 | 6,55 |
--- | --- | --- |
2nd at Folsom | 54 | 190 |
2nd at South Park | 295 | 164 |
2nd at Townsend | 437 | 151 |
5th at Howard | 113 | 177 |
В запросе представлен фрагмент таблицы, в которой указаны начальные и конечные станции для различных маршрутов. В таблице также указано количество поездок между каждой парой станций.
Далее идёт код на языке Python, который выполняет функцию pivot, создавая сводную таблицу с данными из исходного набора данных. В этой таблице показаны все возможные комбинации начальных и конечных станций, даже если они не соответствуют ни одному маршруту. | End Station | 2nd at Folsom | 2nd at South Park | 2nd at Townsend | 5th at Howard | Adobe on Almaden | Arena Green / SAP Center | Beale at Market | Broadway St at Battery St | California Ave Caltrain Station | Castro Street and El Camino Real | Civic Center BART (7th at Market) | Clay at Battery | Commercial at Montgomery | Cowper at University | Davis at Jackson | Embarcadero at Bryant | Embarcadero at Folsom | Embarcadero at Sansome | Embarcadero at Vallejo | Evelyn Park and Ride | Franklin at Maple | Golden Gate at Polk | Grant Avenue at Columbus Avenue | Harry Bridges Plaza (Ferry Building) | Howard at 2nd | Japantown | MLK Library | Market at 10th | Market at 4th | Market at Sansome | Mechanics Plaza (Market at Battery) | Mezes Park | Mountain View Caltrain Station | Mountain View City Hall | Palo Alto Caltrain Station | Park at Olive | Paseo de San Antonio | Post at Kearny | Powell Street BART | Powell at Post (Union Square) | Redwood City Caltrain Station | Redwood City Medical Center | Redwood City Public Library | Rengstorff Avenue / California Street | Ryland Park | SJSU - San Salvador at 9th | SJSU 4th at San Carlos | San Antonio Caltrain Station | San Antonio Shopping Center | San Francisco Caltrain (Townsend at 4th) | San Francisco Caltrain 2 (330 Townsend) | San Francisco City Hall | San Jose City Hall | San Jose Civic Center | San Jose Diridon Caltrain Station | San Mateo County Center | San Pedro Square | San Salvador at 1st | Santa Clara County Civic Center | Santa Clara at Almaden | South Van Ness at Market | Spear at Folsom | St James Park | Stanford in Redwood City | Steuart at Market | Temporary Transbay Terminal (Howard at Beale) |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Мы также можем использовать pivot
, чтобы найти минимальное время в пути между начальной и конечной станциями. Здесь pivot
уже принял необязательный параметр Duration
, а также функцию min
, которая применяется к каждому значению в ячейке.
commute.pivot('Start Station', 'End Station', 'Duration', min)
``` Табличные данные
| Townsend at 7th | University and Emerson | Washington at Kearny | Yerba Buena Center of the Arts (3rd @ Howard) |
| --- | --- | --- | --- |
| 2nd at Folsom | 61 | 97 | 164 |
| 2nd at South Park | 61 | 60 | 77 |
| 2nd at Townsend | 137 | 67 | 60 |
| 5th at Howard | 215 | 300 | 384 |
| Adobe on Almaden | 0 | 0 | 0 |
| Arena Green / SAP Center | 0 | 0 | 0 |
| Beale at Market | 219 | 343 | 417 |
| Broadway St at Battery St | 351 | 424 | 499 |
| California Ave Caltrain Station | 0 | 0 | 0 |
| Castro Street and El Camino Real | 0 | 0 | 0 |
и далее.
В запросе, скорее всего, представлен фрагмент таблицы с данными. Однако без контекста сложно определить, к какой области знаний относится запрос и на каком языке написан исходный текст. Также не хватает информации о том, что необходимо сделать с представленными данными.
Можно предположить, что это таблица с координатами или точками геолокации. Но для точного ответа на вопрос необходим контекст. **Фолсом, станция №2: до Бил-на-Маркет — примерно пять кварталов, очень быстро (271 секунда, около 4,5 минут)**
### Построение карты
Таблица *stations* содержит географическую информацию о каждой станции проката велосипедов, включая широту, долготу и «ориентир» — название города, в котором находится станция.
```py
stations = Table.read_table('station.csv')
stations
station_id | name | lat | long | dockcount | landmark | installation |
---|---|---|---|---|---|---|
2 | San Jose Diridon Caltrain Station | 37.3297 | -121.902 | 27 | Сан-Хосе | 8/6/2013 |
3 | San Jose Civic Center | 37.3307 | -121.889 | 15 | Сан-Хосе | 8/5/2013 |
4 | Santa Clara at Almaden | 37.334 | -121.895 | 11 | Сан-Хосе | 8/6/2013 |
5 | Adobe on Almaden | 37.3314 | -121.893 | 19 | Сан-Хосе | 8/5/2013 |
6 | San Pedro Square | 37.3367 | -121.894 | 15 | Сан-Хосе | 8/7/2013 |
7 | Paseo de San Antonio | 37.3338 | -121.887 | 15 | Сан-Хосе | 8/7/2013 |
8 | San Salvador at 1st | 37.3302 | -121.886 | 15 | Сан-Хосе | 8/5/2013 |
9 | Japantown | 37.3487 | -121.895 | 15 | Сан-Хосе | 8/5/2013 |
10 | San Jose City Hall | 37.3374 | -121.887 | 15 | Сан-Хосе | 8/6/2013 |
11 | MLK Library | 37.3359 | -121.886 | 19 | Сан-Хосе | 8/6/2013 |
(Опущено 60 строк)
Мы можем использовать Marker.map_table, чтобы построить карту с расположением станций проката. Эта функция работает с таблицей, столбцы которой последовательно содержат широту, долготу и каждый пункт имеет необязательный идентификатор.
Marker.map_table(stations.select('lat', 'long', 'name'))
Карта создана с использованием OpenStreetMap — открытой онлайн-системы карт, которую можно использовать так же, как Google Maps или любую другую онлайн-карту. Увеличьте масштаб до Сан-Франциско, чтобы увидеть, как распределены станции. Нажмите на маркер, чтобы узнать, какая это станция.
Вы также можете использовать цветные круги для обозначения точек на карте. Это карта станций проката в Сан-Франциско.
sf = stations.where('landmark', are.equal_to('San Francisco'))
sf_map_data = sf.select('lat', 'long', 'name')
Circle.map_table(sf_map_data, color='green', radius=200)
Станции проката расположены в пяти разных городах. Чтобы различать города, мы сначала используем group для идентификации каждого города и присваиваем каждому городу свой цвет.
cities = stations.group('landmark').relabeled('landmark', 'city')
cities
city | count |
---|---|
Mountain View | 7 |
Palo Alto | 5 |
Redwood City | 7 |
San Francisco | 35 |
Сан-Хосе | 16 |
colors = cities.with_column('color', make_array('blue', 'red', 'green', 'orange', 'purple'))
colors
city | count | color |
---|---|---|
Маунтин-Вью | 7 | синий |
Пало-Альто | 5 | красный |
Редвуд-Сити | 7 | зелёный |
Сан-Франциско | 35 | оранжевый |
Сан-Хосе | 16 | фиолетовый |
Теперь мы можем соединить stations и colors с помощью landmark, а затем выбрать столбцы, необходимые для построения карты.
joined = stations.join('landmark', colors, 'city')
colored = joined.select('lat', 'long', 'name', 'color')
Marker.map_table(colored)
Теперь пять разных городов обозначены пятью разными цветами.
Чтобы увидеть большинство источников аренды, давайте определим начальную станцию:
starts = commute.group('Start Station').sort('count', descending=True)
starts
| Start Station | count | | --- | --- | | Сан-Франциско Caltrain (Townsend at 4th) | 25858 | | Сан-Франциско Caltrain 2 (330 Townsend) | 21523 | | Гарри Бриджес Плаза (Паромное здание) | 15543 | | Временный транзитный терминал (Говард на Бил) | 14298 | | 2nd at Townsend | 13674 | | Таунсенд на 7-м | 13579 | | Стьюарт на рынке | 13215 | | Эмбаркадеро на Сансом | 12842 | | Маркет на 10-м | 11523 | | Рынок на Сансоме | 11023 |
(Опущено 60 строк)
Мы можем включить географические данные, необходимые для отображения этих станций, сначала соединив starts с stations:
station_starts = stations.join('name', starts, 'Start Station')
station_starts
name | station_id | lat | long | dockcount | landmark | installation | count |
---|---|---|---|---|---|---|---|
2-й на Фолсом | 62 | 37,7853 | -122,396 | 19 | Сан-Франциско | 8/22/2013 | 7841 |
2-й в Южном парке | 64 | 37,7823 | -122,393 | 15 | Сан-Франциско | 8/22/2013 | 9274 |
2-й на Таунсенде | 61 | 37,7805 | -122,39 | 27 | Сан-Франциско | 8/22/2013 | 13674 |
5-е на Говарде | 57 | 37,7818 | -122,405 | 15 | Сан-Франциско | 8/21/2013 | 7394 |
Adobe на Алмадене | 5 | 37,3314 | -121,893 | 19 | Сан-Хосе | 8/5/2013 | 522 |
Арена Грин / SAP Центр | 14 | 37,3327 | -121,9 | 19 | Сан-Хосе | 8/5/2013 | 590 |
Бил на рынке | 56 | 37,7923 | -122,397 | 19 | Сан-Франциско | 8/20/2013 | 8135 |
Бродвей-стрит на Баттери-стрит | 82 | 37,7985 | -122,401 | 15 | Сан-Франциско | 1/22/2014 | 7460 |
Станция Caltrain California Ave | 36 | 37,4291 | -122,143 | 15 | Пало-Алто | 14.08.2013 | |
--- | --- | ||||||
Castro Street и El Camino Real | 32 | 37.386 | -122.084 | 11 | Маунтин-Вью | 31.12.2013 | 1137 |
(省略了 58 行)
Сейчас мы извлекаем только те данные, которые необходимы для построения карты. Для каждой станции мы добавляем цвет и площадь. Площадь равна 1000 умноженной на количество арендных дней, начинающихся с каждой станции. Константа 1000 выбрана для того, чтобы круги на карте были нарисованы в соответствующем масштабе.
starts_map_data = station_starts.select('lat', 'long', 'name').with_columns(
'color', 'blue',
'area', station_starts.column('count') * 1000
)
starts_map_data.show(3)
Circle.map_table(starts_map_data)
lat | long | name | color | area |
---|---|---|---|---|
37.7853 | -122.396 | 2nd at Folsom | blue | 7841000 |
37.7823 | -122.393 | 2nd at South Park | blue | 9274000 |
37.7805 | -122.39 | 2nd at Townsend | blue | 13674000 |
(省略了 65 行)
Большая часть Сан-Франциско показывает, что восточная часть города является основным районом аренды велосипедов.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )