Операции замены не работают, потому что 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]