Как построить в цикле отдельные линейные графики?
Строю 7 линейных графиков в одном окне. Когда строю по вбитым значениям вручную, всё получается нормально:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
data = {'Эксперт1':[5, 1, 2, 4, 3],
'Эксперт2':[5, 1, 2, 4, 3],
'Эксперт3':[5, 1, 2, 4, 3],
'Эксперт4':[5, 2, 4, 3, 1],
'Эксперт5':[5, 1, 2, 4, 3],
'Эксперт6':[5, 1, 2, 4, 3],
'Эксперт7':[5, 1, 2, 4, 3],
}
df = pd.DataFrame(data)
x = [1,2,3,4,5]
plt.axis([0,7,0,6])
metki = ( 'утверждение 1', 'утверждение 2', 'утверждение 3', 'утверждение 4', 'утверждение 5')
plt.xticks(x, metki, rotation=60)
plt.plot(x,df)
plt.legend(data, loc='right')
plt.tight_layout()
plt.show()
Но таких значений у меня очень много, все они хранятся в Excel таблице:
Задание 1 Задание 2 Задание 3 Задание 4
Эксперт 1 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 2 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,4,3,5
Эксперт 3 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 4 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,4,3,2,5
Эксперт 5 5,2,4,3,1 1,4,2,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 6 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 7 5,1,2,4,3 1,2,4,3,5 5,3,4,2,1 1,2,4,5,3
Хотелось бы сделать цикл, который будет перебором df.column отрисовывать отдельные графики для каждого задания, но попытки собирать маленькие фреймы данных такого типа для каждого столбца:
Задание 1
Эксперт 1 5,1,2,4,3
Эксперт 2 5,1,2,4,3
Эксперт 3 5,1,2,4,3
Эксперт 4 5,1,2,4,3
Эксперт 5 5,2,4,3,1
Эксперт 6 5,1,2,4,3
Эксперт 7 5,1,2,4,3
не увенчались успехом из-за того, что в столбцах нечисловые значения.
df = pd.read_excel('Значения.xlsx', sheet_name='Задания', index_col=[0])
df1 = df.pivot_table(index=df.index, values='Задание 1')
pandas.core.base.DataError: No numeric types to aggregate
Что я могу предпринять в такой ситуации?
График для выхода по каждому столбцу выглядит вот так
Данные здесь.
Ответы (4 шт):
У вас действительно, у вас в каждой клетке EXCEL таблице не числа, а текст.
Оставив с стороне вопрос, зачем сделано так извращенно, вам надо из исходного файла сделать CSV файл с сепаратором, например ";" и прочитать этот файл в Pandos, получив датафрейм с столбцом, в которых записаны текст. Могу предположить, что что-то подобное вы уже сделали.
Теперь значения в каждой клетке второго столбца разбить (метод split c разделителем ",") на новые столбцы, по ходу превращая их в целые числа. И уже по этому новому датафрейму строить графики.
Всего этого можно было бы избежать, если бы в вашей исходной таблице каждая реакция вашего Эксперта заносилась бы в отдкльную клетку. Почему вы так не сделали - вам виднее.
попробуйте сделать так:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("tasks.csv", index_col=0)
fig, ax = plt.subplots(figsize=(12,8))
for i in df.columns[:1]: # строим только для первой колонки
data = df[i].str.split(",", expand=True).fillna(0).astype("int")
# выше использован метод fillna потому, что у вас в файле есть последнее задание
# у которого у седьмого эксперта отсутствует значение.
for j in range(len(data)):
plt.plot(range(1, len(data.iloc[j])+1), data.iloc[j])
plt.legend(df.index,loc='right')
plt.show()
Возможно, вам стоит задуматься о разнесении заданий по разным графикам
В общем, с большщой помощью экспертов, получилось сделать как-то так.
for col in df.columns:
for j in df[col]:
data = list(map(int, j.split(",")))
x = [1, 2, 3, 4, 5]
plt.axis([0, 7, 0, 5])
plt.plot(x, data, linewidth=0.5)
for k in list(zip(x, data)):
plt.annotate(k[1], (k[0], k[1]), va='top', ha='center')
plt.legend(df.index, loc='right')
metki_x = ('выбрано первым', 'выбрано вторым', 'выбрано третьим', 'выбрано четвёртым', 'выбрано пятым')
plt.xticks(x, metki_x, rotation=60)
metki_y = ('-', 'утверждение 1', 'утверждение 2', 'утверждение 3', 'утверждение 4', 'утверждение 5')
plt.yticks(np.arange(6), metki_y, rotation=60)
plt.tight_layout()
plt.title("{}".format(str(col)))
Входные данные (в каждой ячейке фрейма находится CSV строка):
In [76]: df
Out[76]:
Задание 1 Задание 2 Задание 3 Задание 4
Эксперт 1 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 2 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,4,3,5
Эксперт 3 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 4 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,4,3,2,5
Эксперт 5 5,2,4,3,1 1,4,2,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 6 5,1,2,4,3 1,2,4,3,5 2,1,3,4,5 1,2,3,4,5
Эксперт 7 5,1,2,4,3 1,2,4,3,5 5,3,4,2,1 1,2,4,5,3
Векторизированное решение - парсим столбец с CSV данными в DataFrame с целыми значениями. Т.е. из каждого столбца получается DataFrame. И рисуем получившийся фрейм:
def parse_csv_col(col, sep=",", dtyp="int", col_prefix="утверждение "):
res = col.str.split(sep, expand=True).astype(dtyp)
res.columns += 1
return res.add_prefix(col_prefix)
parse_csv_col(df["Задание 1"]).T.plot(rot=60)
plt.tight_layout()
Результат:


