Сделайте график из CSV-файла с тысячами записей в Python
У меня есть этот код в Python, который работает.
from matplotlib import style
from matplotlib import pylab as plt
import numpy as np
style.use('ggplot')
filename='results.csv'
value=[]
date=[]
import csv
with open(filename, 'r') as csvfile:
csvreader = csv.reader(csvfile)
for row in csvreader:
if len(row) ==2:
value.append(row[0])
date.append(row[1])
value=np.array(value)
import datetime
for ii in range(len(date)):
date[ii]=datetime.datetime.strptime(date[ii], '%a %b %d')
plt.ylim(2, -2)
plt.plot(date, value)
plt.show()
И файл.csv (почти 18000 записей):
[0.0] Thu Mar 15
[0.0] Thu Mar 15
[0.0] Thu Mar 15
[0.0] Thu Mar 15
[-0.05] Thu Mar 15
[0.0] Thu Mar 15
[0.0] Thu Mar 15
....
Итак, когда я запускаю код, я получаю такой результат:
Дело в том, что я хочу, чтобы значения по оси Y от [-2,2] в порядке возрастания, чтобы наблюдать маршрут сюжетной линии. Является ли мое обоснование для визуализации такого CSV неправильно или я пропустил что-то важное? Буду признателен за любую помощь.
2 ответа
У ваших ценностей есть окружающие скобки, не знаю почему. Когда я пытаюсь этот код с numpy 1.14.1 и matplotlib 2.0.0, он выдает исключение, что вы не можете конвертировать [0.0] в float.
После попытки этого кода в Anaconda (matplotlib 2.1.2 и numpy 1.14.0) код работает. Однако y-Scale отображается неправильно. Я думаю, что может быть ошибка в одном из этих пакетов.
Прежде всего, вы должны преобразовать значение [0.0] с помощью eval (из пакета ast) в список, а затем взять первый элемент списка. Так что просто измените ваше значение.
import ast
.
.
value.append(ast.literal_eval(row[0])[0])
После этого вы настраиваете отображение matplotlib от 2 до -2. Вы должны установить ylim так:
plt.ylim(-0.05, 2)
Итак, полный пример
from matplotlib import style
from matplotlib import pylab as plt
import numpy as np
import ast
style.use('ggplot')
filename='results.csv'
value=[]
date=[]
import csv
with open(filename, 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter='\t')
for row in csvreader:
if len(row) ==2:
value.append(ast.literal_eval(row[0])[0])
date.append(row[1])
value=np.array(value)
import datetime
for ii in range(len(date)):
date[ii]=datetime.datetime.strptime(date[ii], '%a %b %d')
plt.ylim(-0.05, 2)
plt.plot(date, value)
print(value)
plt.show()
Более того, есть гораздо лучшие решения для вашей задачи. Подумайте об использовании панд. Я предположил, что вам нужен 2018 год.
from matplotlib import style
from matplotlib import pylab as plt
from dateutil.parser import parse
import datetime
import pandas as pd
import ast
style.use('ggplot')
filename = 'results.csv'
df = pd.read_csv('results.csv', sep='\t')
df.columns = ['value', 'date']
# Convert to datetime
df.date = df.date.apply(lambda x:
parse(x, default=datetime.datetime(2018, 1, 1)))
# Unpack your list elements
df.value = df.value.apply(lambda x: ast.literal_eval(x)[0])
plt.plot(df.date, df.value)
plt.ylim(-0.05, 2)
plt.show()
Как уже упоминалось в комментариях, использование eval является проблемой безопасности. Лучше использовать literal_eval из пакета ast.
Использование панд намного упрощает вещи. Вы можете непосредственно снять скобки с данных при чтении файла.
u = u"""[0.0]\tThu Mar 14
[0.0]\tThu Mar 15
[0.0]\tThu Mar 16
[0.0]\tThu Mar 17
[-0.05]\tThu Mar 18
[2.0]\tThu Mar 19
[0.0]\tThu Mar 20"""
import io
import pandas as pd
import matplotlib.pyplot as plt
import datetime
parse_date = lambda x: datetime.datetime.strptime(x, "%a %b %d")
parse_vals = lambda x: float(x.strip("[]"))
df = pd.read_csv(io.StringIO(u), sep="\t",header=None,names=["val", "date"],
converters={0:parse_vals,1:parse_date} )
df.set_index("date").plot()
plt.show()