LINUX.ORG.RU

Mapper, reducer на Python

 


0

0

Всем привет! Только начал разбираться в питоне, больше в приложении к Hadoop. Есть тестовое задание, на реализации кода которого я пока просто ухожу в аут, хотя задание явно простое. Если есть желающие, подскажите реализацию? (питон 2)

P.S.> какие-то баллы за задание или еще какие-то бенефиты меня не интересуют, всё только чтобы понять реализацию

Есть файл csv c записями вида Пользователь,Исполнитель,Число прослушиваний,Число пропусков:

userId,artistId,plays,skips
0,336,1,0
0,718,1,0
0,730,2,1
0,816,1,1

Вам необходимо проделать следующее:

  1. Оставьте в данных только тех пользователей, для которых сумма plays строго больше 1000. Сколько таких пользователей?

т.е. должно быть построковое считывание файла, группировка <ключ(в данном случае userid), plays> Затем подать этот промежуточный результат на второй скрипт (reducer), который по ключу userid просуммирует plays

Примеры гугляться с wordcount, но из него я не вывез переделку)

питон 2

No way

т.е. должно быть

Если совсем в лоб, то:

  • читай по строкам, пихай всё в dict, с ключами userId, суммируя по ходу plays
  • потом отфильтруй ключи по условию plays > 1000
  • и ещё один цикл по входному файлу, построчное чтение, проверка что userId присутствует в фильтре и запись удовлетворяющих строк в выходной файл

А так, наверное pandas умеет это всё красивее.

Через map, reduce, filter это тоже всё делается красиво, но для «Только начал разбираться в питоне» будет не так просто как «в лоб».

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 2)
Ответ на: комментарий от vvn_black

No way

Через Zeppelin такая вот фигня

Через map, reduce, filter

спасибо, буду копать

WanderVanger
() автор топика
plays = {}
for l in open('file.csv'):
  try: l = map(int, l.split(',')) # в py3 так уже не взлетит, оптимизаторы херовы;-(
  except: pass
  plays.setdefault(l[0], [0])[0] += l[2]
plays = dict(filter(lambda x: x[1][0]>1000, plays.items()))
print len(plays) # число юзеров

Питон2 почти во всем лучше питон3. Его главный недостаток - его перестают включать в современные дистрибутивы. Потому что типа немодно и немолодежно.

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от AntonI

map(int, l.split(‘,’)) # в py3 так уже не взлетит, оптимизаторы херовы;-(

import csv

mx__ ★★★★★
()
Ответ на: комментарий от AntonI

Питон2 почти во всем лучше питон3. Его главный недостаток - его перестают включать в современные дистрибутивы. Потому что типа немодно и немолодежно.

map(int, l.split(',')) в третьем питоне записывается как:

[int(i) for i in l.split(',')]

или

functools.map(int, l.split(','))

В чём горе-то заключается?

Python 3 объективно лучше Python 2, по почти всем параметрам. И портировать код не так уж сложно, большая часть кода вообще без изменений одинаково работает. Перевёл несколько больших проектов с Py2 на Py3 за последние 4 года, ни разу это не вызвало затруднений.

emorozov
()
Ответ на: комментарий от emorozov

в третьем питоне записывается как: [int(i) for i in l.split(‘,’)]

или

[*map(), ]

или

list(map())
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от emorozov

Python 3 объективно лучше Python 2, по почти всем параметрам

В своих задачах я не вижу ни одного, кроме мб юникода. Да и то, появление bytes как отдельного типа это нивелирует полностью.

Если в Ваших задачах не так - рад за Вас.

Про 2to3 обсуждали 100500 раз, лень повторяться. Простота зависит от проекта.

AntonI ★★★★★
()
Ответ на: комментарий от AntonI

В своих задачах я не вижу ни одного

Специально не сравнивал, но из важных вещей, что ещё вижу я:

  • аннотации типов (помогают отлавливать ошибки, которые сложно обнаружить тестами, и получающийся код лучше документирован, понятнее)
  • встроенная отладка утечек памяти (раза четыре в жизни приходилось отлаживать утечки памяти в Python 2, и это было кошмарно сложно, новые возможности ещё не использовал, но выглядят полезными)
  • async/await

И это прямо сразу, из головы, специально не задумываясь. Если посидеть и подумать, наверняка, больше вспомнилось бы.

А так, у каждого свои задачи, конечно.

emorozov
()
Ответ на: комментарий от emorozov

Там где нужны аннотации и пр. я пользую плюсы:-) Да и в общем типизация и в пай2 через декораторы нормально прикручивалась.

А вот проверять глазками овер 500 операций деления по кодовой базе py2 при переходе на py3 мне все еще не хоцца. Самое обидное, что ни одну из серьезных родовых травм питона при сломе обратной совместимости так и не вылечили…

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)

Есть тестовое задание

Может, не стоит тогда пытаться идти туда, где даже тестовое задание не можете осилить? Плюс займете место того, кто с этим справится.

cdshines ★★★★★
()
Ответ на: комментарий от AntonI

Питон2 почти во всем лучше питон3

Нет, не так. Питон2 почти во всём то же самое, что и Питон3. Но на третью версию стоит стоило переходить даже только из-за человеческой работы с текстом и кодировками. f-строки — тоже топчик.

fun = lambda s,x: bytes(b+x for b in s.encode()).decode('koi8-r')
print(f"{fun('string', 0b_0110_0000) = }")
fun('string', 0b_0110_0000) = 'стринг'

Потому что типа немодно и немолодежно.

Нет. Потому, что поддерживать две ветки всю жизнь никто не собирается.

anonymous
()
Ответ на: комментарий от AntonI

Спасибо, очень изящное решение!

plays.setdefault(l[0], [0])[0] += l[2]

unsupported operand type(s) for +=: ‘int’ and ‘str’

я так понимаю, из-за разных типов переменных нельзя слепить их вместе

WanderVanger
() автор топика

file = 'plays.csv'

cols = open(file).readline().strip()

sql = '''echo '
.mode csv
.import %s Plays

SELECT %s FROM Plays
JOIN (
    SELECT userId AS uid,sum(plays) AS total_plays
    FROM Plays GROUP BY uid
) ON userId=uid WHERE total_plays > 1000
' | sqlite3
''' % (file, cols)

print(cols); __import__('os').system(sql)

anonymous
()

Для задачи map reduce не нужен. Все делается с помощью pandas.
Если не влезает в pandas или надо по ядрам распараллелить, есть надстройка над пандасом с map reduce - dask
А сабж imho в job.

Shadow ★★★★★
()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от WanderVanger

WTF?

У меня не грузится.

Выложите прям сюда скрипт и короткий пример входных данных (строчек 10)

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от peregrine

Да, я со студиозусов нынешних ору. Студенты бауманки ищут репетитора по С (!!!) - книжки нынче читать немодно и немолодежно.

Третий курс ВМК МГУ не владеет адресной арифметикой.

Второй курс бауманки не асилил комплексных чисел.

Этот список можно продолжать… че в заборостроительных техникумах с гордым именем академия-чего-то-там твориться лучше вообще не рассказывать.

AntonI ★★★★★
()
Ответ на: комментарий от peregrine

Я не понимаю, почему эти люди потом пррграммерами работают

Shadow ★★★★★
()
Ответ на: комментарий от deep-purple

как минимум миддл, потоком

я менеджер и немного датасатанист.
Зачем csv потоком? Чанками же. Это же таблицы! Они 50 лет чанками обрабатываются.
Ну и любимое:

import dask.dataframe as dd
ddf = dd.read_csv(filename)

- в ddf объект из автоматически оптимизированных по размеру массивов pandas датафреймов, с ленивыми вычислениями и невидимым map-reduce.

Shadow ★★★★★
()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от AntonI

Да, я со студиозусов нынешних ору. Студенты бауманки ищут репетитора по С (!!!) - книжки нынче читать немодно и немолодежно.

По си нужен репетитор? Я понимаю там C++, сложно может быть - ехала абстракция на шаблоне и паттерном погоняла, но чем репетитор то поможет? Надо брать, читать книжку и смотреть на гитхабе как люди нормальные делают.

Третий курс ВМК МГУ не владеет адресной арифметикой.

Это замечательно, не надо с адресной арифметикой джунов выпускать. Потом такое пишется, что смотреть страшно.

Второй курс бауманки не асилил комплексных чисел.

В смысле не осилил? Там осиливать то только i=sqrt(-1) и то что решений у уравнений больше чем в школе учили (ну и элементарные арифметические действия с ними + тригонометрическое представление). Или им надо что-то более жесткое, вроде формулы Муавра? Ну а если они не осилили что-то с комплексными числами, вроде рассчёта электрических цепей или поля с математики, то это уже они физику или матан не осилили.

peregrine ★★★★★
()
Ответ на: комментарий от AntonI

Не зазнавайся, ты тоже много чего не осилил.

anonymous
()
Ответ на: комментарий от Shadow

ну ты же читаемый поток данных в огрниченый по размеру буфер кладешь - вот и чанки

deep-purple ★★★★★
()

Выкинь hadoop нафиг, он такие древние пакеты внутри себя в зависимостях тащит, что секьюрити сканеры плачут от боли. Ну и как тебе выше посоветовали, хоть пандусом решай. Он очень крут для табличной обработки данных.

manntes-live ★★★
()
Ответ на: комментарий от deep-purple

С сильно кривым csv ты ничего не сделаешь даже будь ты трижды сеньор. Если csv хоть как-то соответствует спецификации, то всё будет нормально, а если пол файла csv, пол файла json, а половина файла война и мир в виде fb2 с картинками в base64, то ничего не поможет.

peregrine ★★★★★
()
Ответ на: комментарий от Shadow

Ну вот ты значит и есть тот самый джун про которого deep-purple говорит. Потому что пандасом чанками csv обрабатывают совсем не так)

https://github.com/pandas-dev/pandas/pull/38225

Иначе будет у тебя memory error когда csv будет побольше чем оперативки в пекиче. Потому что память выделится правильно жирно, а потом тебе ещё потребуется сверху память для обработки.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 2)
Ответ на: комментарий от peregrine

Иначе будет у тебя memory error когда csv будет побольше чем оперативки в пекиче

Здесь нет никакой ложки pandas. Смотри, я читаю csv dask'ом: он создаёт ленивый объект, который для юзера выглядит как массив датафреймов pandas, а сам «автомагически» делает им map-reduce, в том числе проверяя доступный RAM и количество ядер для обработки.

Shadow ★★★★★
()
Ответ на: комментарий от AntonI

Питон2 почти во всем лучше питон3.

ОМГ

замени unicode на string

Jopich1
()
Ответ на: комментарий от Shadow

Тьфу, в глаза долблюсь и пандас везде вижу, сорри

peregrine ★★★★★
()
Ответ на: комментарий от thunar

Угораздило читать там спецкурс. Для спецкурса нужны были оду и комплексные числа. - А у нас не было таких чисел! - говорит аудитория. Ок, объясняю, посмотрите еще грю хоть в вики хоть где, рассказываю еще че то, в конце пятиминутка - почти никто комплексные числа не понял.

Второе занятие, ай-яй говорю, объясняю второй раз, еще че то рассказываю, в конце пятиминутка - почти никто комплексные числа не понял.

На третьем занятии говорю - ребята, у нас будет зачет. И зачёт будет начинаться с того, что каждый сев ко мне отвечать сначал при мне сходу решает один пример на комплексные числа и одно оду. Решил - говорим дальше, не решил - пересдача.

Там такой стон по аудитории пронесся, аж сердце сжалось… После этого они зашевелились хоть как то.

AntonI ★★★★★
()
Ответ на: комментарий от peregrine

С сильно кривым csv ты ничего не сделаешь даже будь ты трижды сеньор

Ну вот, ты даже задачу решать не начал, а уже руки опустил. Тем не менее, уже согласен с тем, что задача эта совсем не простая.

то ничего не поможет

Нормальный парсер, учитывающий все кейсы и состояния — поможет. Но его же написать надо, да?

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Нормальный парсер, учитывающий все кейсы и состояния — поможет. Но его же написать надо, да?

csv парсер в питоне (который родной и встроенный в стандартную библиотеку) норм или нет? Ну и да, не такой уж он и сложный, хотя да, если с нуля писать, то наверное с джуном я погорячился.

https://hg.python.org/cpython/file/tip/Modules/_csv.c

https://github.com/python/cpython/blob/main/Lib/csv.py

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

csv парсер в питоне (который родной и встроенный в стандартную библиотеку) норм или нет?

Не знаю. В отрыве конкретно от питона, но:

Лет 10 назад, в одной фирме где я работал, в b2b систему была добавлена возможность импорта csv.

Блондинки начали загружать туда всякий треш с битыми кодировками, нестандартными сепараторами и отсутствием экранирования. В поисках адекватного варианта, парсеры менялись как перчатки, но они не справлялись с детектированием всего этого дерьма и молча пропускали невалид дальше, что влекло за собой, в худшем случае, засирание базы кривыми данными.

Довольно быстро стало ясно, что проще будет написать свой с нуля. Только так проблемы и закончились.

Почему же авторы перепробованых нами парсеров не удосужились нормально продумать и протестировать свои поделки? Хороший вопрос. Джуны, что-ли? Ведь из каждого утюга говорится: нельзя доверять данным, получаемым извне.

Добавлю, что, уже достаточное количество раз, при трудоустройстве, получив тестовое задание «от силы на пару дней», я с такими сроками был категорически не согласен, ибо куча не уточнённых моментов, нюансов использования и отсюда во много раз разросшиеся сроки реализации. У нас происходил разговор, примерно похожий на нынешний «про парсер» и работодатель сливался. Ну а то! Кому-то я там в каждый из разов ЧСВ наждачкой неплохо так почёсывал.

deep-purple ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.