pandas.объединение и плохие/поврежденные данные

#python #pandas #dataframe #csv

Вопрос:

Я использую pd.concat для объединения 15 000 CSV-файлов. Некоторые CSV-файлы испорчены (повреждены?) данные, которые мне не нужны.

Код, который я использую для объединения:

 for filename in files:
    try:
        df1 = pd.read_csv(filename, index_col=None, header=0, error_bad_lines=False, warn_bad_lines=True, quotechar=None, quoting=3, sep = ' ', skiprows=1, lineterminator='n', engine='c', encoding='utf-8')
    except UnicodeDecodeError:
        df1 = pd.read_csv(filename, index_col=None, header=0, error_bad_lines=False, warn_bad_lines=True, quotechar=None, quoting=3, sep = ' ', skiprows=1, lineterminator='n', engine='c', encoding='cp1252')

li.append(df1)

data = pd.concat(li, axis=0, ignore_index=True, join='inner')
 

Приведенный выше код работает, и я могу объединить все файлы. Однако выходной CSV теперь содержит некоторые неверные данные, которые вызывают у меня проблемы (типы данных столбцов изменяются на объект). По сути, хотя я и использую error_bad_lines=False, мои CSV-файлы все еще содержат неверные данные.

Пример csv-файла, содержащего хорошие и плохие данные:

 1554309123 03-APR-2019 17:32:03    0.0    0.0  292.4    0  307.6     0.0     0.0   40    0.0    0     0.0     0.0    0.0
1554309841 03-APR-2019 17:44:01    0.0    0.0  292.4    0  307.6     0.0     0.0   40    0.0    0     0.0     0.0    0.0
1554309911 03-APR-2019 17:45:11    0.0    0.0  292.4    0  307.6     0.0     0.0   40    0.0    0     0.0     0.0    0.0
1554309911 03-APR-2019 17:45:11    0.0    0.0  292.4    0  307.6     0.0     0.0   40    0.0    0     0.0     0.0    0.0                                                                                                                                                                                                                                                                                                    [šê;C®ÃtkïÎÒ««¹sÛI‹sÀÂ’¿†­ï0TÆÞ²¾ÝÙ¡êž¡ÛÎìío2ã¼XA¿amp;FÍä=€ Z>Žö6¿œ:½Y.5:õÖl›WFøM¦Z¦ÓY‡*Ýêåêïàa×.ªþÛs ãßEŽßØ»rûú‡ËÆzøa6[8Ù:HWw/çUÄõ†^`BHdê<amp;ži„ñ‡tòPXÞ€êáÆ6Ò‡ÀÁ£Œ3ÒX£7☣Ž;òØ£?¤CY¤‘G"™¤’žt–—x«‘e ‡ûýæQw%¦Ý‹PŽ¥Õxahšgí-9ˆ
W÷•u`n8X‚þ­gÑTÖéÆ[•¢Qùå™    amp;6ЉeÊñsIkJ±×Ó‰dútÔUkV)SFçX*N(æ^å*QƒºèèiýÙi^”¨_T.˜U”vQ~jféÒ‡¦^Úé²É êdþ>Zá¢m¢pZiź%ÝœLÌÙ"› -Å›ºöqY
|]„l¶¸amp;„“œKׂȵê%‰´rV¯Ç f ÔÆ¡.Å"{j¥ÂêÛ€1X9 §ø¾Kâ»)ܪ‹¶}ë¼sìI_rö廂~êåeñYåT,íǨp,VÌàÂy€ëä¦Bê×”aŽ9°‚:)¬æ–årLq«Ç<jËiܳÏ?´ÐC]´ÑG#´ÒK3Ý´ÓOCµÔSS]µÕWcµÖ[sݵ×_ƒ¶Øc“]¶Ùg£¶Úk³Ý¶Ûo÷ÜsÓ]·Ýwã·Þ{óݷ߸àƒ^¸á‡#ž¸âA†  ;                                                                                                                                                                                                                                                                                                                                                                                                                   ¨Ê2Bð“;̤¥XÌc"ó~­då0u'H?^Ž–Elß%A¹KQ®íš²œä©yÊeÂxÚŒ%9Ë   M‚S˜ÜæÙÍ®™ëÌÝ[yHJ›°Übüú¸È:‚’†–¦>ϘþÎpø3“‘§#ÑÈÄ}æR¡˜üaO§Iu2¡ôŒamp;‹ùÉRÔœñœgH%§D‚fÓ‹Eamp;.›©·—´¥¬¥A]ºRµÁ’q*E  sZIlž-ˆ6­¨ !*ÐmÊ´…Ó%QßÇÊ{"5©c<$L5jУö´žd§MHÁ™Öò•LYËjÖ³¢5­j] [ÛêÖ·Â5®r ]ëj×»âu£Ó¬j(C:¿J•©Þ,¨XCIÒ”Ž5°ê5#ÊÓ<¢3¦yíG¹¨Î’Þ4—9íª1«ZÍ_Š1«ƒ<lfXRО¶›?¬7²ºE‚q“3e$AF¯Êð‹¼(UiGþÛU…ö„êH¯zÏ­ö´‘¬mmb9[È6ÎŒ£ågA5˜<ÝŠ–©i#ƒ[õ§amp;½`b
«ÜåF¥œÃî6òÍj:–§ÔÅ'砩«Jwªj{Ï©ÈBš7¾èÍY~C‡Òñ®Rž~}Å|iZ9ÃÖšÁ­.LNäz‘“ç
ðVLàM
 

Таким образом, плохие данные объединяются в другой CSV. Это вызывает проблемы, поскольку фрейм данных изменяется с типа столбца int/float64 на объект. Для того, чтобы я мог работать с данными, мне нужно сохранить их в соответствии с их предполагаемым типом данных, но, очевидно, неверные данные объединяются, и столбец изменяется на объектный тип данных.

Если бы плохие данные были просто «Null/NaN», я знаю, что мог бы решить эту проблему. Однако некоторые неверные данные технически являются нормальными (неверные данные содержат смесь нулей, странных символов юникода, букв, цифр и т.д.) И поэтому не пропускаются error_bad_lines=False

Вопрос 1: Есть ли способ удалить строки данных, которые не имеют указанного разделителя? Я считаю, что это было бы действительно хорошим решением.

Вопрос 2: Другое решение, однако не столь подходящее, из-за того, что в проблемных CSV-файлах есть ХОРОШИЕ данные. Я использую GLOB для загрузки всех CSV-файлов. Возможно, у меня есть способ закодировать его так, чтобы глоб пропускал файлы, содержащие плохие/поврежденные данные?

Редактировать:

 data.dropna(inplace=True)
 

Это удаляет большинство нулевых значений, но не строки. Все еще есть плохие данные в строковом формате в столбцах, которые должны содержать только int/float

Ответ №1:

Я бы действительно углубился в аргументы, чтобы pd.read_csv . Они здесь твои друзья. Конкретно:

  • dtypeType имя или указание столбца -> тип, необязательно>
    Тип данных для данных или столбцов. например {‘a’: np.float64, ‘b’: np.int32, ‘c’: ‘Int64’} , Используйте str или объект вместе с подходящими настройками na_values, чтобы сохранить и не интерпретировать dtype. Если указаны преобразователи, они будут применяться ВМЕСТО преобразования dtype.
  • usecols список-подобный или вызываемый, необязательно
    Возвращает подмножество столбцов. Если это похоже на список, все элементы должны быть либо позиционными (т. е. целочисленными индексами в столбцах документа), либо строками, соответствующими именам столбцов, предоставленным пользователем в именах или выведенным из строки(строк) заголовка документа. Например, допустимым параметром usecols, подобным списку, будет [0, 1, 2] или ['foo', 'bar', 'baz'] . Порядок элементов игнорируется, поэтому usecols=[0, 1] он такой же, как [1, 0]. Чтобы создать экземпляр фрейма данных из данных с сохраненным порядком элементов, используйте pd.read_csv(data, usecols=['foo', 'bar'])[['foo', 'bar']] для столбцов в ['foo', 'bar'] порядке или pd.read_csv(data, usecols=['foo', 'bar'])[['bar', 'foo']] для ['bar', 'foo'] порядка.

    Если вызываемая функция может быть вызвана, вызываемая функция будет оценена по именам столбцов, возвращая имена, в которых оценивается вызываемая функция True . Будет приведен пример допустимого вызываемого аргумента lambda x: x.upper() ['AAA', 'BBB', 'DDD'] . Использование этого параметра приводит к гораздо более быстрому времени синтаксического анализа и меньшему использованию памяти.

Их можно использовать в сочетании для принудительного применения типов данных и имен столбцов, которые вы ожидаете увидеть в каждом файле. Если вы укажете точные столбцы , которые вы ожидаете увидеть usecols , и в определенном файле отсутствуют столбцы или его невозможно прочитать, вы получите ошибку ValueError. Если вы укажете тип для одного из своих столбцов и значение не совпадет, вы получите ошибку типа. Тогда вы сможете обращаться с ними изящно.