df.fillna или df.replace не исключают NaN в моем файле .csv - PullRequest
1 голос
/ 19 января 2020

Я знаю, что здесь множество подобных вопросов. Но ни один из ответов, похоже, не работает для меня. Обратите внимание, что я начинающий программист и узнал об этом только через Youtube Tutorials. Обратите внимание, что я использую ОС Ma c и PyCharm

Моя программа загружает этот файл .csv через этот код, который я нашел на Youtube

def download_data(csv_url):
    response = request.urlopen(csv_url)
    csv = response.read()
    csv_str = str(csv)
    lines = csv_str.split ("\\n")
    dest_url = r'NO_AM1H.csv'
    fx = open(dest_url,"w")
    for line in lines:
        fx.write (line + "\n")
    fx.close()

I затем прочитайте .csv и установите разделитель. Много значений в .csv <7 или пусто (NaN). Я пытаюсь заменить их, как показано на рисунке, однако при печати кадра данных (df) он по-прежнему показывает NaN и <7 </p>

df = pd.read_csv('NO_AM1H.csv',delimiter=';')
df = df.replace(np.nan,0)
df = df.replace('<7',0)

print(df.tail(4))

Любая помощь будет принята с благодарностью и принесет извинения за любые ошибки ладьи ie , Спасибо

Ответы [ 4 ]

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

Быстрое исправление, которое вы можете сделать, пометить возможные значения NA при чтении CSV, что-то вроде этого:

Метод 1:

df = pd.read_csv('NO_AM1H.csv',delimiter=';', na_values=['<7', 'NaN','nan', None])

# then fill the NAs
df = df.fillna(0)

Метод 2:

df = df.applymap(lambda x: None if x == '<7' else x)

Обходной путь замены плавающих NA в pandas:

df = df.applymap(lambda x: 0 if str(x) == 'nan' else x)
0 голосов
/ 20 января 2020

Операции замены не работают, потому что DataFrame содержит только один столбец, где каждая строка содержит всю строку из CSV в виде одной строки. Причиной этого является первая строка файла, #ZEITBEREICH: 18.01.2019 bis 19.01.2020, которая выглядит как какой-то комментарий, нарушает синтаксический анализ файла. Мы можем избежать этой проблемы, используя несколько из множества аргументов для pandas.read_csv():

Old:

df = pd.read_csv('NO_AM1H.csv',delimiter=';')

New:

df = pd.read_csv('NO_AM1H.csv', delimiter=';', header=0, skiprows=[0])

Этого изменения достаточно исправить синтаксический анализ и, в свою очередь, заменить операции.


Далее следует вопрос о кодировке. Чтобы процитировать документы для urllib.request:

Обратите внимание, что urlopen возвращает объект байтов. Это связано с тем, что urlopen не может автоматически определять кодировку потока байтов, который он получает от HTTP-сервера. В общем случае программа будет декодировать возвращенный объект байтов в строку, как только определит или угадает соответствующую кодировку.

Ваш код неправильно декодирует данные, что означает, например, второе и имена третьего столбца становятся AABU NO AM1H [\xb5g/m\xb3] и BIEL NO AM1H [\xb5g/m\xb3] соответственно. Это не было бы такой проблемой, если бы не тот факт, что метод .headers.get_content_charset() объекта ответа, по-видимому, дает сбой, возвращая None для этого конкретного файла.


download_data() функция также излишне сложна. Вот рабочее решение, которое по стилю похоже на ваш исходный код:

from urllib import request

import numpy as np
import pandas as pd

pd.options.display.width = 0


def download_data():
    csv_url = "https://www.lanuv.nrw.de/fileadmin/lanuv/luft/temes/NO_AM1H.csv"
    response = request.urlopen(csv_url)
    resp_contents = response.read().decode('ISO-8859-1')
    with open('../out/csv_test_out.csv', 'w') as out_file:
        out_file.write(resp_contents)


download_data()

df = pd.read_csv('../out/csv_test_out.csv', delimiter=';', header=0, skiprows=[0])
df = df.replace(np.nan, 0).replace('<7', 0)

df.head():

        Datum   Zeit  ... WAST NO AM1H [µg/m³] WULA NO AM1H [µg/m³]
0  18.01.2019  01:00  ...                    0                    0
1  18.01.2019  02:00  ...                    0                    0
2  18.01.2019  03:00  ...                    0                    0
3  18.01.2019  04:00  ...                    0                    0
4  18.01.2019  05:00  ...                    0                    0

[5 rows x 59 columns]

Я думаю, что мы можем сделать намного лучше, хотя:

import pandas as pd

pd.options.display.width = 0

csv_url = "https://www.lanuv.nrw.de/fileadmin/lanuv/luft/temes/NO_AM1H.csv"

df = pd.read_csv(filepath_or_buffer=csv_url,
                 encoding='ISO-8859-1',
                 header=0,
                 skiprows=[0],
                 comment='#',
                 parse_dates=[[0, 1]],
                 converters={1: lambda val: '23:59' if val == '24:00' else val},
                 na_values=['<7'],
                 delimiter=';')

df.iloc[:, 1:] = df.iloc[:, 1:].fillna(0).astype('Int64')

df.head():

           Datum_Zeit  ...  WULA NO AM1H [µg/m³]
0 2019-01-18 01:00:00  ...                     0
1 2019-01-18 02:00:00  ...                     0
2 2019-01-18 03:00:00  ...                     0
3 2019-01-18 04:00:00  ...                     0
4 2019-01-18 05:00:00  ...                     0

[5 rows x 58 columns]
0 голосов
/ 20 января 2020

Я скопировал содержимое файла прямо из браузера, и он работает. Помните, что заголовок начинается во второй строке.

enter image description here

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

Думаю, у вас проблема с кодировкой.

В linux я использовал

file -i NO_AM1H.csv

, который сказал мне, что кодировка файла NO_AM1H.csv: text / plain; charset = iso-8859-1

Затем я импортирую его с помощью read_csv и указываю кодировку.

Попробуйте это,

import pandas as pd
import numpy as np

df = pd.read_csv('NO_AM1H.csv', sep=';',header=0, encoding='iso-8859-1')

df = df.replace(np.nan,0)
df = df.replace('<7',0)

и похоже,

              Datum   Zeit AABU NO AM1H [µg/m³]  ... WALS NO AM1H [µg/m³] WAST NO AM1H [µg/m³] WULA NO AM1H [µg/m³]
8780  18.01.2020  21:00                    0  ...                    0                    0                    0
8781  18.01.2020  22:00                    0  ...                    0                    0                    0
8782  18.01.2020  23:00                    0  ...                    0                    0                    0
8783  18.01.2020  24:00                    0  ...                    0                    0                    0

для .head () и .tail ()

обратите внимание, я изменил ваш исходный файл и удалил первую строку (строка 0).

update: if у вас все еще есть пустые строки, затем попробуйте,

df=df.replace(r'^\s*$', np.nan, regex=True)  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...