Первоначально Написал Джон Хэмминк
Как ученый, работающий с данными, или любой, кто заинтересован в сборе данных по этому вопросу, несомненно, полезно знать о том, как собирать данные в вашем приложении — данные, которые вы захотите позднее запрашивать и анализировать.
Здесь мы создадим приложение на Python из AZ, итерируем его, чтобы сделать его более надежным, и, наконец, добавим регистрацию событий приложения с помощью Fluentd и Treasure Data. Мы выбрали Python, потому что он быстро становится языком выбора среди начинающих ученых данных. В наших примерах мы будем использовать Python версии 2.7.
В следующем разделе мы рассмотрим еще больше языков программирования и сред, а также визуализацию (используя такие инструменты, как Tableau и Chartio), но сейчас давайте начнем с изучения некоторых основ Python, прежде чем перейти к сбору данных.
Камень, ножницы … бумага?
Для нашего примера сегодня мы создадим базовое приложение « камень, бумага, ножницы» . (Что касается вас, ищущих работу, то это может или не может быть тем, о чем вас спросят в случайном интервью по кодированию, поэтому обратите внимание!) С его помощью мы будем собирать данные о:
- игрок
- Выбор
- решение суда
Для тех из вас, кто не знаком с концепцией Rock-Paper-Scissors, давайте спросим Википедию :
Камень-ножницы-бумага … — это игра с нулевой суммой, в которой каждый игрок одновременно формирует одну из трех фигур вытянутой рукой. Этими формами являются «камень» (простой кулак), «бумага» (плоская рука) и «ножницы» (кулак с указательным и средним пальцами, образующими букву V). В игре есть только три возможных результата, кроме ничьей: игрок, решивший сыграть в рок, побьет другого игрока, выбравшего ножницы («ножницы для дробления камня»), но проиграет тому, кто играл в бумагу («бумага покрывает камень») ; игра бумаги проиграет игре ножниц («ножницы режут бумагу»). Если оба игрока бросают одну и ту же фигуру, игра завязывается и обычно сразу переигрывается, чтобы разорвать ничью.
Что касается меня, я изучил игру, наблюдая, как несколько детей играют в нее на улице перед моим домом. Возможно, также было проведено собеседование по кодированию.
Основное приложение
import random
tie= "a tie"
p1 = "Player 1; Player 2 loses"
p2 = "Player 2; Player 1 loses"
myDict = {('rock', 'rock') : tie, ('rock', 'paper') : p2,
('rock', 'scissors') : p1, ('paper', 'rock') : p1, ('paper', 'paper') : tie, ('paper', 'scissors') : p2, ('scissors', 'rock') : p2, ('scissors', 'paper') : p1, ('scissors', 'scissors') : tie }
def throw(player1, player2):
verdict = myDict[(player1, player2)]
print "The game goes to " + verdict
print "Ya wanna play Rock, Paper, Scissors?"
player1 = raw_input("Throw! Choose 'rock', 'paper', or 'scissors': " )
print "Player 1 chooses: " + player1
player2 = random.choice(['rock', 'paper', 'scissors'])
print "Player 2 chooses: " + player2
throw(player1, player2)
Примечание: прокрутите для просмотра полного кода
Листинг 1: rsp.py
Несколько замечаний:
- В наших целях у нас будет игра игрока против компьютера, поэтому мы будем использовать Python raw_input (), чтобы получить ввод игрока, и random.choice (), чтобы сгенерировать ввод компьютера. Обратите внимание, что мы импортировали случайную библиотеку в начале.
- Мы будем использовать словарь Python (myDict) для поиска вердикта по паре ключ: значение. Наш ключ к поиску — это пара вариантов player1 и player2. Мы используем функцию throw () для этого поиска и сохраняем наш вердикт в связанной переменной. Кстати, словари, как правило, являются хорошим способом сделать что-то в Python и намного лучше, чем очень длинная строка операторов if… then… else.
Запуск игры с
$ python rsp.py
Производит следующий вывод:
Ya wanna play Rock, Paper, Scissors?
Throw! Choose ‘rock’, ‘paper’, or ‘scissors': rock
Player 1 chooses: rock
Player 2 chooses: scissors
The game goes to Player 1; Player 2 loses
Интересно отметить, что в настоящее время мы не обрабатываем никаких ошибок. Если мы играем в игру и выбираем что-то кроме камня, бумаги или ножниц, мы получаем ошибку:
Throw! Choose ‘rock’, ‘paper’, or ‘scissors': moar paper
Player 1 chooses: moar paper
Player 2 chooses: rock
Traceback (most recent call last):
File “rsp.py”, line 21, in <module>
throw(player1, player2)
File “rsp.py”, line 13, in throw
verdict = myDict[(player1, player2)] KeyError: (‘moar paper’, ‘rock’)
Для Эрр … Ну, для Эрр
Давайте справимся с этой ошибкой. Мы переместим входные данные проигрывателя и функцию throw () в блок try / Кроме того, чтобы наше приложение могло восстановиться (и не завершиться сбоем), если пользователь введет неправильный ввод. Мы также вызовем эту функцию, чтобы повторить, если пользователь вводит неправильную вещь:
def lets_get_started():
try:
player1 = raw_input("Throw! Enter 'rock', 'paper', or 'scissors': " )
print "You chose: " + player1
player2 = random.choice(['rock', 'paper', 'scissors'])
print "The computer chose: " + player2
throw(player1, player2)
except KeyError:
print "Hey! I said enter 'rock', 'paper' or 'scissors'! Try again."
lets_get_started()
Отредактируйте ваш файл так, чтобы он выглядел так:
import random
tie= "is a tie"
p1 = "goes to you; the computer loses."
p2 = "goes to the computer; you lose."
myDict = {('rock', 'rock') : tie, ('rock', 'paper') : p2,
('rock', 'scissors') : p1, ('paper', 'rock') : p1, ('paper', 'paper') : tie, ('paper', 'scissors') : p2, ('scissors', 'rock') : p2, ('scissors', 'paper') : p1, ('scissors', 'scissors') : tie }
def throw(player1, player2):
verdict = myDict[(player1, player2)]
print "The game " + verdict
def lets_get_started():
try:
player1 = raw_input("Throw! Enter 'rock', 'paper', or 'scissors': " )
print "You chose: " + player1
player2 = random.choice(['rock', 'paper', 'scissors'])
print "The computer chose: " + player2
throw(player1, player2)
except KeyError:
print "Hey! I said enter 'rock', 'paper' or 'scissors'! Try again."
lets_get_started()
print "Ya wanna play Rock, Paper, Scissors?"
lets_get_started()
Листинг 2: rsp-better.py
Попробуйте! Попробуйте и с неверными данными. Теперь, когда это работает лучше и обрабатывает неверные данные, давайте подумаем о том, как мы можем собирать данные о наших пользователях и записывать их в облако.
Войдите это!
Перед настройкой входа в приложение необходимо включить несколько вещей в своей среде. (Для получения дополнительной информации см. Http://docs.treasuredata.com/articles/python .)
Сначала установите TD-агент
$ curl -L http://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh
Затем обновите /etc/td-agent/td-agent.conf, чтобы включить ваш ключ API
type tdlog
apikey 5919/
auto_create_table
buffer_type file
buffer_path /var/log/td-agent/buffer/td
...
Далее перезапустите Treasure Agent:
cookie@monster-ThinkPad-X1:~omnomnom/python$ sudo /etc/init.d/td-agent restart
При перезапуске Treasure Agent вы должны увидеть следующее состояние на консоли:
* Перезапуск td-agent td-agent [OK]
И последнее, но не менее важное: убедитесь, что вы установили fluent-logger в вашу среду Python:
$ pip install fluent-logger
Как мы уже упоминали ранее, теперь мы хотим собрать данные о
- выбор нашего пользователя;
- выбор компьютера;
- вердикт к игре.
Сбор комментариев к журналу для отправки в Treasure Data через Treasure Agent очень прост. Использование функции события из плавной библиотеки представляет собой одну строку кода:
from fluent import event
…
event.Event('game_data', {'player': 'Player 1', 'choice': player1 })
Это запишет в нашу базу данных (в таблице с именем ‘game_data’) два столбца (со связанными значениями): ‘player’ (со значением, содержащим строку ‘Player 1’) и ‘choice’ (со значением, содержащим содержимое переменная player1, которая была выбором между «камнем», «бумагой» или «ножницами», которые мы получили в виде необработанного ввода от пользователя).
Давайте обновим нашу программу, чтобы записать оба варианта и вердикт игры в Treasure Data.
Под оператором import random, но перед объявлениями переменных, добавьте эти два оператора import:
from fluent import sender
from fluent import event
Далее, давайте настроим нашу отправительную и локальную базу данных, чтобы она могла отправлять данные в Treasure Data:
sender.setup('td.rsp_db', host='localhost', port=24224)
Наконец, мы добавим наши события регистрации. Во-первых, в нашей функции throw () после того, как мы напечатаем вердикт, давайте запишем его:
event.Event('game_data', {
'verdict': verdict
})
Войти оба выбора игрока. После того, как вы напечатаете выбор игрока 1, зарегистрируйте его:
event.Event('game_data', {
'player': 'Player 1',
'choice': player1
})
Сделайте то же самое для игрока 2, заменив игрока 1 игроком 2 и переменными соответственно. Когда вы будете готовы, ваш код должен выглядеть как этот файл на github .
Теперь попробуйте запустить ваш файл несколько раз, чтобы заполнить базу данных. Как это работает для вас? Вы столкнулись с какими-либо проблемами? Пожалуйста, оставьте комментарии ниже.
Запрашивающий разум хочет знать
Итак, мы играли в нашу игру несколько тысяч раз и хотим заполнить базу данных. Как мы запрашиваем нашу базу данных?
Один из способов увидеть, что готовится в вашем экземпляре локальной базы данных, — использовать TD Toolbelt непосредственно из bash для запроса и просмотра экземпляра локальной базы данных.
Чтобы просмотреть таблицы в запущенном экземпляре, попробуйте команду td tables (щелкните изображение, чтобы увеличить его):
Вы также можете запустить команду tail, чтобы увидеть самые последние строки вашей локальной базы данных:
$td table:tail rsp_db game_data
{“time”:1429579380,”player”:”Player 2″,”choice”:”paper”}
{“time”:1429579383,”player”:”Player 1″,”choice”:”scissors”}
{“time”:1429579383,”verdict”:”goes to you; the computer loses.”}
…
Однако в конечном итоге вы захотите запрашивать данные не с устройства, на котором работает ваше приложение, а из облака.
Иногда это помогает очистить буфер Treasure Agent для более быстрой загрузки данных в Treasure Data в облаке. Для этого выполните следующую команду:
$ kill -USR1 cat /var/run/td-agent/td-agent.pid
Теперь у нас должна быть возможность перейти к консоли Treasure Data, чтобы выполнить несколько разных запросов. Для этого войдите на сайт http://www.treasuredata.com и нажмите кнопку «Новый запрос» в правом верхнем углу.
В окне New Query мы должны выбрать базу данных. Попробуйте выполнить несколько простых запросов в консоли, чтобы познакомиться с тем, что в настоящее время находится в вашей таблице:
Select * from game_data
Это покажет вам первые 100 строк в вашей базе данных в порядке убывания, и выберите count (1) из game_data вернет количество строк в вашей таблице.
Конечно, когда вы начнете выполнять аналитику ваших данных, вам захочется сделать больше, чем просто эти простые запросы, поэтому ознакомьтесь с нюансами запросов Hive и Presto . Presto в настоящее время находится в стадии разработки, поэтому, будучи очень мощным, он будет иметь несколько ограничений, которые неправильно переводятся в стандартный SQL.
(Нажмите на картинку для увеличения).
Мы также можем запускать запросы непосредственно из нашего скрипта, если мы подключены к правильному ключу API.
Отсюда вы можете запросить данные в Treasure Data для использования на выбранной вами платформе визуализации, такой как Tableau, Chartio и другие. Мы рассмотрим это в следующем посте. Оставайтесь в курсе!
Узнайте больше на http://docs.treasuredata.com/articles/python