1. Python / Говнокод #17886

    −116

    1. 1
    df[df['reason']=='in-in error sequence']['spider'].value_counts().to_csv('spiders_out-out-seq.csv')

    Страшно?

    Запостил: kyzi007, 30 Марта 2015

    Комментарии (98) RSS

    • Ы, забыла ошибку именования вывода поправить,
      Ответить
    • Перегруженные __equals__() и __getitem__() для быстрой фильтрации?
      Ответить
    • >df[df['reason']=='in-in error sequence']
      Что за формат такой?
      Ответить
      • побуду кэпом - в df по ключам True/False лежат дикты, имеющие по ключу spider объекты с методом value_counts,...
        Ответить
      • Или сравнение с объектом по строковым ключам df порождает функцию/объект, который при передаче в качестве ключа производит поиск.фильтрацию данных.
        Похожий подход используется в numpy, там можно написать что-то вроде
        a[a < 0] = 0
        чтобы обнулить все отрицательные элементы.
        Ответить
        • И как numpy видит это a<0? Оно готовый бул получает.
          Ответить
          • перегруженные операторы сравнения и индексирования
            Ответить
            • Нихуя не понял.

              a.__lt__(0) возвращает объект, хранящий условие, которой потом передается как индекс?
              Ответить
              • Да. Первый раз видишь чтоли? Кругом и рядом такое используется для построения DSL. В крестах это называется Expression Pattern.
                Ответить
                • В питоне за пределом numpy, который большинству нахуй не упал, это не используется. Алсо, на питоне есть парсер, на котором таки можно писать нормальные DSL. И 0>a написать нельзя будет.
                  Ответить
                  • А что предлагаешь вместо Нумпая? Юлию? Р? Матлаб? У меня данных нет, но подозреваю, что Нумпай таки самый популярный пакет для работы со статистикой.
                    Ответить
                    • > статистика большинству нахуй не упала
                      Ответить
                      • А чем определяется нужность? И кто такие большинство? И как востребованость большинством отражается на востребованости вообще?
                        Ответить
                        • Большинство - это большинство юзеров. И как востребованость большинством отражается на неактуальности проблемы для питона в целом.
                          Ответить
                          • А где-то есть статистика по тому кто и для чего использует Питон?
                            Почему мнение нубов должно кого-то волновать?
                            Почему, например, вклад в развитие языка и инфраструктуры не является параметром для вычисления востребованости?
                            Ответить
                            • Статистики у меня под рукой нет, но, думаю, мы тут наблюдаем один из феноменов интернета, когда крикливое меньшинство (ультранационалисты, прыщеблядки и прочий скам) кажется гораздо больше, чем оно есть на самом деле. Вот облюбовали вузовцы педивикию - и кажется, что на питоне только графики статистики и рисуют.

                              >Почему мнение нубов должно кого-то волновать?
                              Пардон, но хелловердщики / быдлокодеры на numpy и есть нубы по сравенению с веб-девелами, которые используют гораздо большую часть языка, а не пишут си на питоне. Или есть пруфы на противное?
                              Ответить
                    • J
                      Ответить
                      • Хороший выбор, только нужно вникнуть. Я вникаю - мне нравится
                        Ответить
                  • Можно таким же макаром, например, SQL-фильтры писать, составляя из них выражения и рендеря потом в текст запроса. У нас такой подход используется в одной из абстракций хранилища.

                    Ну и мне интересно, насколько часто люди пишут 0 < X вместо X > 0.
                    Это, безусловно, недостаток. В основном убогой ООП-говноконцепции "только объекты, только вызовы методов" и питушиной динамизации.

                    В крестах, например, можно без проблем написать перегрузку оператора для полной симметрии.
                    MyExpression operator<(int value, MyField field);
                    MyExpression operator>(MyField field, int value);
                    Ответить
                    • А в питоне симметричный оператор используется только если у левой части нет своей перегрузки?
                      Ответить
                      • В питоне a+b вызывает a.__add__(b), если его нет - b.__radd__(a)
                        Ответить
                      • > своей перегрузки
                        думаю, перегрузка - не совсем правильное слово в контексте пистона.
                        Ответить
                        • ...в контексте ООП
                          Ответить
                          • Поясните мысль.

                            как перегрузка связана с ООП?
                            Ответить
                            • В питоне перегрузка оператора = перегрузка метода. Очевидно же.
                              Ответить
                              • В пистоне вообще нет ПЕРЕГРУЗКИ, есть только ПЕРЕОПРЕДЕЛЕНИЕ. См. overloading vs overriding.
                                Ответить
                                • Какая нахуй разница?
                                  Ответить
                                  • Ты кроме динамики ничего не видел, тебе долго объяснять.
                                    Ответить
                                    • Видел статику. Долго - не объясняй, все равно нормально объяснить не сможешь.
                                      Ответить
                • > В крестах это называется Expression Pattern.
                  Это такая штука, из-за которой появилось boost::lambda? Ну и забористое же курево было у разрабов, тоже хочу.

                  > Кругом и рядом такое используется для построения DSL.
                  Ото всей души надеюсь, что никогда такого не встречу :)
                  Ответить
                  • Апофеоз всего этого добра - boost.proto, поверх которого уже реализована lambda и прочий expressive. А начиналось всё, насколько я знаю, с вычислительной алгебры в Blitz++.
                    Ответить
          • a<0 превращается в булев массив размерности как a, где истинны только элементы, соответствующие элементам a<0.
            Любой массив можно проиндексировать булевым массивом такой же размерности, получив view (одномерный массив) элементов для которых индекс истинен. Если над этим view производить операции, будет затронут исходный массив.
            Ответить
            • http://govnokod.ru/17886#comment269430

              Массив - это list или хрень из numpy? В питоне можно как-то так:
              lst[1,3..5,9]
              Ответить
              • Массив нумпишный. Про сравнения отписал ниже.
                Ответить
        • Тогда у тебя сравнение будет несимметричным.
          Ответить
          • >>> import numpy
            >>> a = numpy.array([1,2,3,4])
            >>> a<3
            array([ True, True, False, False], dtype=bool)
            >>> 3>a
            array([ True, True, False, False], dtype=bool)
            Ответить
            • Каг? http://govnokod.ru/17886#comment269618
              Ответить
              • Смотри, какая тут фишка... для арифметических операций предусмотрены обратные версии методов, потому что если сложение/умножение еще симметричны (хотя по идее не всегда), то вот вычитание/деление - нет.
                А вот сравнение считается симметричным, так что если 3.__gt__(a) возвращает NotImplemented, то интерпретатор пробует зайти с другого фланга и вызывает a.__lt__(3), что уже срабатывает нормально.

                Во всяком случае, я так понял доки.
                Ответить
                • А где у int вообще методы сравнения?
                  Ответить
                  • В смысле "где"? int это субкласс object. В Питоне всё объект. =)
                    Ответить
                    • В смысле dir(3)
                      Ответить
                      • >>> int.__gt__
                        <method-wrapper '__gt__' of type object at 0x1E1DB538>

                        Тут я и сам не очень понял, но вблизи корня дерева объектов всегда творится какая-то чертовщина. В какой-то момент им же надо перейти к нативному коду.
                        Ответить
                        • int().__gt__
                          AttributeError: 'int' object has no attribute '__gt__'

                          Да, различия между сишным апи и питоновским заябывают.
                          Ответить
                    • Кстати, во втором питоне - нет.
                      Ответить
                      • Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
                        Type "help", "copyright", "credits" or "license" for more information.
                        >>> issubclass(int, object)
                        True
                        >>> isinstance(3, object)
                        True
                        Ответить
                        • >В Питоне всё объект.

                          In [29]: class A: pass

                          In [30]: isinstance(A(), object)
                          Out[30]: True

                          Стоп, а нахуя тогда явно наследоваться от объекта?
                          Ответить
                          • Во втором питоне есть какая-то хуйня с old style и new style классами. Вторые явно наследуются, первые неявно. Другой разницы навскидку не скажу. Обратная совместимость что ли. В третьем old style уже нету.
                            Ответить
                            • Во втором new style только через явное наследование, ты не путаешь? Иначе нахера нас учили это писать?
                              Ответить
                              • Могу только привести копипасту:

                                Up to Python 2.1, old-style classes were the only flavour available to the user. The concept of (old-style) class is unrelated to the concept of type: if x is an instance of an old-style class, then x.__class__ designates the class of x, but type(x) is always <type 'instance'>. This reflects the fact that all old-style instances, independently of their class, are implemented with a single built-in type, called instance.

                                New-style classes were introduced in Python 2.2 to unify classes and types. A new-style class is neither more nor less than a user-defined type. If x is an instance of a new-style class, then type(x) is typically the same as x.__class__ (although this is not guaranteed - a new-style class instance is permitted to override the value returned for x.__class__).

                                Ряд фишек типа property доступен только новым классам.
                                Ответить
                                • Нахуй эти изъебства нужны? Единственное что я успел заметить - __slots__ работают только если класс наследует объект
                                  Ответить
                                  • Да как обычно, сначала сделали как получилось, потом переделали, а потом пришла она - обратная совместимость(tm)
                                    Ответить
                                    • Так зачем переделали? Зачем нужно наследовать object?
                                      Ответить
    • Нас этим не испугать.
      У меня в проекте вот такое есть
      if (isset($suppliers_makes_data[$list_office_logo[$j]][$list_supplier_logo[$j]][$list_direction[$j]][$make_logo]['max_price']) && $suppliers_makes_data[$list_office_logo[$j]][$list_supplier_logo[$j]][$list_direction[$j]][$make_logo]['max_price']>0)
      и ничего жив здоров. Переписываю потихоньку
      Ответить
    • Похоже на pandas. Крутая либа.
      df - от DataFrame.
      А фишка с индексацией называется "fancy indexing"
      Ответить
      • Да, это пандас и да это статистика. Я начала накидывать в коммандлайне отчет потом плюнули и все таки написана нормально. Когда показала в чатике народ начал меня упрекать в говнокоде.
        Собственно я недоосилила мерж датафреймов и сделала наполовину руками.
        class StatsReport(State):
            def run(self):
                path = self.context.storage.abs_path('')
                df = pandas.read_csv(path + 'report_error.csv')
                errors = set(df['reason'].values)
        
                tmp = map(lambda x: {'spider': x[0], 'all': x[1]}, df['spider'].value_counts().to_dict().items())
                report = {}
                for r in tmp:
                    report[r['spider']] = r
        
                for error in errors:
                    if len(str(error)) == 1:
                        continue
                    tmp = map(lambda x: {'spider': x[0], 'val': x[1]}, df[df['reason'] == error]['spider'].value_counts().to_dict().items())
                    for r in tmp:
                        report[r['spider']][error] = r['val']
        
                for r in report.itervalues():
                    for error in errors:
                        if error not in r:
                            r[error] = 0
                    for key in r.keys():
                        if key != 'spider':
                            r[key] = int(r[key])
        
                json.dump(map(lambda x: x, report.itervalues()), open(path + 'error_stats_report.json', 'w+'))
        Ответить
        • Говно в формате, где в нулевом элементе лежит что-то одно, в первом - что-то другое (но как я понял это либа?). Для вас, Козлов, NamedTuple построили.
          Ответить
          • Тут все равно будет одно и то же значение после вызова value_counts и его типизировать может только задрот от ооп.
            И да, пандас далеко не везде удобность потому что оно должно работать быстро.
            Ответить
            • Где тут? У тебя items() возвращает кортежи/списки с 2 элементами, назначение которых можно понять только заглянув куда-то в доки.
              Ответить
              • Ну многое можно узнать только заглянув в доки, я не собираюсь кого то либе учить. Тем более что делает код можно смотреть риалтайм. Есть print obj.__doc__ и print dir(obj)
                Ответить
                • Но сказать что делает df[df['reason']=='in-in error sequence'] не заглянув в доки нельзя. Были бы строковые ключи / поля - было бы понятно
                  Ответить
              • Не понимая как работат пандас в код с работой с ним лучше не лезть, много специфики.
                Ответить
                • Самое хреновое, что так ведет себя и стандартная либа питона, poplib кажется, там возвращается кортеж (код, ответ)
                  Ответить
        • map(lambda x: x

          Э-э. Это заглушка?
          Ответить
          • Это особая питонячья магия) Просто json итераторы не ест.
            Ответить
            • map(lambda x: x, report.itervalues())

              Бля, ну это же на отдельный гк тянет :) или report.values(), или list()
              Давно на питоне?
              Ответить
              • Год )
                Ответить
              • Честно говоря вот только что занялась тем что учу что то, до этого просто выезжала на гугле и смекалке и было лень.
                Ответить
            • Кстати, почему?
              Ответить
              • Яхз, не разбиралась, работает и ладно, тем более что с той либы надо сваливать на что то более адкватное. А за report.values() стыдно.
                Ответить
                • list(sequense) важнее имхо
                  Ответить
                  • Флешерское прошлое до сих пор дает о себе знать фразами "Оо а что можно было"?
                    Ответить
        • А какой смысл использовать open() и не закрывать? (Вместо with).
          Я так предполагаю, что все эти map(lambda ...) можно было короче и компактнее переписать циклами.
          Т.е. map(lambda x: x[0], x[1], something.to_dict().items()) явно же лучше было записать:
          [for key, value in something.to_dict().items()], а может и to_dict() не нужно было...
          Ответить
          • >А какой смысл использовать open() и не закрывать? (Вместо with).
            В одну строчку тип. Если серьезно, что плохого в таком коде? Говорят, что удаление ссылок не гарантирует удаление объекта гц, но обычно почему-то он удаляется, это явно не мегапроект, где это было бы важно.

            >переписать циклами
            Списковыми выражениями?
            Ответить
        • Короче, тут хорошо очень многое.
          Ответить
    • if len(str(error)) == 1:
      continue

      Тот самый код?
      Ответить
      • Ну вы поняли какой
        Ответить
      • Там в нескольких случаях попала ерунда в ошибку )
        Ответить
        • Что за ерунда? Т.е. это костыль какой-то?
          Ответить
          • Да, мне было не особо интересно, там мало бажных данных получилось. Как нить найду поправлю.
            Ответить
            • Ну если работающий костыль так хуй с ним, просто интересно что там за ошибки такие приходили
              Ответить
              • То что я анализировала это 60мб ная выжимка с ошибками из всех данных, где то я в процессе ее создания налажала, но там буквально несколько строк битые.
                Ответить
              • Просто взять и поанализировать сырую статистику не представлялось возможным, я там пошардила данные, покусочно обрабатывала и скидала ошибки, возможно оно как раз между кусками выросло (там вообще интересно было потому что по гб данным были раскиданы айдишники, миллион где то, по которым надо было проследить корректность порядка сбора данных). То есть дохрена млн записей по времени раскиданных. Наверно самая моя интрересная задача, а решилась после подумать и раздупления пандаса в два щелчка.
                Ответить
    • for key in r.keys():
                      if key != 'spider':

      Вот тут мне аж похорошело :) Обход циклом словаря
      Ответить
      • Что не так?
        Ответить
      • Как бы ты исправил этот код?
        Ответить
        • if 'spider' in r:

          r же у нас dict?
          Ответить
          • Эм... Вообще не то.
            Ответить
            • Тьху. Монитор галимый, без ide вижу плохо.
              Ответить
              • > Эм... Пояснишь?
                Не думал, что нужно тебе это объяснять, но этот код
                for key in r.keys():
                    if key != 'spider':
                        r[key] = int(r[key])
                Преобразует в int значения для всех ключей, кроме ключа 'spider'. Как твой код решает эту же задачу, я не понял.
                Ответить
              • В первом случае некоторый код выполняется для всех элементов словаря, где ключ не spider
                А во втором - проверяется есть ли такой ключ.
                Мне кажется или это немного не то?
                Ответить
        • Можно было dict.pop_key('spider', None) без проверок все сделать, что там надо в цикле, и потом вернуть ключ обратно.
          Ответить
    • tmp = [{ 'spider': 1 }, { 'spider': 2 }, { 'spider': 3 }, { 'spider': 4 }, { 'spider': 5 }]
      report = {}
      for r in tmp:
          report[r['spider']] = r
      
      report = dict((x['spider'], x) for x in tmp)
      report = { x['spider']: x for x in tmp }


      Ну и еще вот это можно было короче записать.
      Ответить
      • Не, не.
        Я расскажу что происходит
        Берется баальшой пак данных состоящий из записей типа id | spider | error type | url | time, смотрятся какие есть ошибки, смотрятся какие есть спайдеры.
        Берется каждая ошибка, по ней смотрится количество ошибок для каждого спайдера. Потом это количество приводится к тому инту которое жрет json + спайдеры по которым в данной категории нету ошибок ставится ключ и значение 0.
        То есть получается таблица типа
        спайдер | количество ошибок а | количество ошибок б
        От этого и все пляски.
        Я позже буду строить другие фасеты по конкретным потокам данных которые светятся чаще всего и по времени когда это происходит)
        Ответить
        • Так все три варианта выше делают одно и то же, просто последнее - короче.
          Ответить

    Добавить комментарий