Почему pandas .read_fwf не пропускает пустую строку в соответствии с инструкциями? - PullRequest
1 голос
/ 15 января 2020

Я читаю формат фиксированной ширины ( полный исходный файл ), полный отсутствующих данных, поэтому pandas.read_fwf пригодится. После заголовка есть пустая строка, поэтому я передаю skip_blank_lines=True, но это, похоже, не имеет никакого эффекта, так как первая запись все еще заполнена NaN / NaT:

import io
import pandas

s="""USAF   WBAN  STATION NAME                  CTRY ST CALL  LAT     LON      ELEV(M) BEGIN    END

007018 99999 WXPOD 7018                                  +00.000 +000.000 +7018.0 20110309 20130730
007026 99999 WXPOD 7026                    AF            +00.000 +000.000 +7026.0 20120713 20170822
007070 99999 WXPOD 7070                    AF            +00.000 +000.000 +7070.0 20140923 20150926
008260 99999 WXPOD8270                                   +00.000 +000.000 +0000.0 20050101 20100920
008268 99999 WXPOD8278                     AF            +32.950 +065.567 +1156.7 20100519 20120323
008307 99999 WXPOD 8318                    AF            +00.000 +000.000 +8318.0 20100421 20100421
008411 99999 XM20                                                                 20160217 20160217
008414 99999 XM18                                                                 20160216 20160217
008415 99999 XM21                                                                 20160217 20160217
008418 99999 XM24                                                                 20160217 20160217
010000 99999 BOGUS NORWAY                  NO      ENRS                           20010927 20041019
010010 99999 JAN MAYEN(NOR-NAVY)           NO      ENJA  +70.933 -008.667 +0009.0 19310101 20200111
010013 99999 ROST                          NO                                     19861120 19880105
010014 99999 SORSTOKKEN                    NO      ENSO  +59.792 +005.341 +0048.8 19861120 20200110
"""

print(pandas.read_fwf(io.StringIO(s), parse_dates=["BEGIN", "END"],
      skip_blank_lines=True))

, что приводит к :

USAF     WBAN         STATION NAME  ... ELEV(M)      BEGIN        END
0       NaN      NaN                  NaN  ...     NaN        NaT        NaT
1    7018.0  99999.0           WXPOD 7018  ...  7018.0 2011-03-09 2013-07-30
2    7026.0  99999.0           WXPOD 7026  ...  7026.0 2012-07-13 2017-08-22
3    7070.0  99999.0           WXPOD 7070  ...  7070.0 2014-09-23 2015-09-26
4    8260.0  99999.0            WXPOD8270  ...     0.0 2005-01-01 2010-09-20
5    8268.0  99999.0            WXPOD8278  ...  1156.7 2010-05-19 2012-03-23
6    8307.0  99999.0           WXPOD 8318  ...  8318.0 2010-04-21 2010-04-21
7    8411.0  99999.0                 XM20  ...     NaN 2016-02-17 2016-02-17
8    8414.0  99999.0                 XM18  ...     NaN 2016-02-16 2016-02-17
9    8415.0  99999.0                 XM21  ...     NaN 2016-02-17 2016-02-17
10   8418.0  99999.0                 XM24  ...     NaN 2016-02-17 2016-02-17
11  10000.0  99999.0         BOGUS NORWAY  ...     NaN 2001-09-27 2004-10-19
12  10010.0  99999.0  JAN MAYEN(NOR-NAVY)  ...     9.0 1931-01-01 2020-01-11
13  10013.0  99999.0                 ROST  ...     NaN 1986-11-20 1988-01-05
14  10014.0  99999.0           SORSTOKKEN  ...    48.8 1986-11-20 2020-01-10

[15 rows x 11 columns]

Строка 0 по-прежнему имеет значения для всех столбцов. Я ожидал, что строка 0 будет первой непустой строкой данных, начиная с 007018. Почему skip_blank_lines=True, похоже, не имеет никакого эффекта? Как я могу сказать pandas пропустить пустую строку? Я что-то не так делаю?

Ответы [ 2 ]

1 голос
/ 15 января 2020

В вашем коде отсутствует одна деталь: вам не удалось передать параметр widths .

Но это еще не все. Другая проблема заключается в том, что, к сожалению, read_fwf содержит такую ​​ошибку, что игнорирует параметр skip_blank_lines .

Чтобы справиться с этим, определите следующий класс , содержащий readline метод пропуска пустых строк:

class LineFilter(io.TextIOBase):
    def __init__(self, iterable):
        self.iterable = iterable

    def readline(self):
        while True:
            line = next(self.iterable).strip()
            if line:
                return line

Затем запустите:

df = pd.read_fwf(LineFilter(io.StringIO(s)), widths=[7, 6, 30, 8, 6, 8, 9, 8, 9, 9],
    parse_dates=["BEGIN", "END"], na_filter=False)

Как видите, я добавил na_filter = False блокировать преобразование пустых строк в NaN значения.

0 голосов
/ 15 января 2020

Если есть один столбец, который будет иметь какое-то значение, если вы удалите пустую строку для этого столбца, это может сработать.

Попробуйте ниже

df.dropna(subset=['WBAN'], how='all', inplace=True)
print(df.head())
...