Как построить в цикле отдельные линейные графики?

Строю 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 шт):

Автор решения: passant

У вас действительно, у вас в каждой клетке EXCEL таблице не числа, а текст.

Оставив с стороне вопрос, зачем сделано так извращенно, вам надо из исходного файла сделать CSV файл с сепаратором, например ";" и прочитать этот файл в Pandos, получив датафрейм с столбцом, в которых записаны текст. Могу предположить, что что-то подобное вы уже сделали.

Теперь значения в каждой клетке второго столбца разбить (метод split c разделителем ",") на новые столбцы, по ходу превращая их в целые числа. И уже по этому новому датафрейму строить графики.

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

→ Ссылка
Автор решения: strawdog

попробуйте сделать так:

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()

Возможно, вам стоит задуматься о разнесении заданий по разным графикам

введите сюда описание изображения

→ Ссылка
Автор решения: Io Io

В общем, с большщой помощью экспертов, получилось сделать как-то так.

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)))
→ Ссылка
Автор решения: MaxU

Входные данные (в каждой ячейке фрейма находится 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()

Результат:

введите сюда описание изображения

→ Ссылка