Как сделать подзаголовки столбцов в кадре данных Pandas в одном окне внутри цикла for - PullRequest
0 голосов
/ 21 января 2019

* Помогите, пожалуйста, это очень важно: почему невозможно получить участки сюжета кадра данных Pandas с помощью HeatMap внутри цикла for?

Я пытаюсь создать графы столбцов в pandas dataframe внутри цикла for во время итераций, так как я строю результаты для каждого цикла, для каждые 480 значений , чтобы получить все 3 субплота, принадлежащих A, B , C рядом в одном окне. Я нашел только один ответ здесь , который, я боюсь, не мой случай! @ euri10 ответил, используя flat .

Мои сценарии следующие:

# Import and call the needed libraries
import numpy as np
import pandas as pd
import os
import seaborn as sns
import matplotlib.pyplot as plt


'''
Take a list and create the formatted matrix
'''
def mkdf(ListOf480Numbers):
    normalMatrix = np.array_split(ListOf480Numbers,8)     #Take a list and create 8 array (Sections)
    fixMatrix = []
    for i in range(8):
        lines = np.array_split(normalMatrix[i],6)         #Split each section in lines (each line contains 10 cells from 0-9)
        newMatrix = [0,0,0,0,0,0]                         #Empty array to contain reordered lines
        for j in (1,3,5):
            newMatrix[j] = lines[j]                       #lines 1,3,5 remain equal
        for j in (0,2,4):
            newMatrix[j] = lines[j][::-1]                 #lines 2,4,6 are inverted
        fixMatrix.append(newMatrix)                 #After last update of format of table inverted (bottom-up zig-zag)
    return fixMatrix

'''
Print the matrix with the required format
'''
def print_df(fixMatrix):
    values = []
    for i in range(6):
        values.append([*fixMatrix[4][i], *fixMatrix[7][i]])  #lines form section 6 and 7 are side by side
    for i in range(6):
        values.append([*fixMatrix[5][i], *fixMatrix[6][i]])  #lines form section 4 and 5 are side by side
    for i in range(6):
        values.append([*fixMatrix[1][i], *fixMatrix[2][i]])  #lines form section 2 and 3 are side by side
    for i in range(6):
        values.append([*fixMatrix[0][i], *fixMatrix[3][i]])  #lines form section 0 and 1 are side by side
    df = pd.DataFrame(values)
    return (df)

'''
Normalizing Formula
'''

def normalize(value, min_value, max_value, min_norm, max_norm):
    new_value = ((max_norm - min_norm)*((value - min_value)/(max_value - min_value))) + min_norm
    return new_value

'''
Split data in three different lists A, B and C
'''

dft = pd.read_csv('D:\me4.TXT', header=None)
id_set = dft[dft.index % 4 == 0].astype('int').values
A = dft[dft.index % 4 == 1].values
B = dft[dft.index % 4 == 2].values
C = dft[dft.index % 4 == 3].values
data = {'A': A[:,0], 'B': B[:,0], 'C': C[:,0]}
#df contains all the data
df = pd.DataFrame(data, columns=['A','B','C'], index = id_set[:,0])  


'''
Data generation phase

'''

#next iteration create all plots, change the number of cycles
cycles = int(len(df)/480)
print(cycles)
for i in df:
    try:
        os.mkdir(i)
    except:
        pass
    min_val = df[i].min()
    min_nor = -1
    max_val = df[i].max()
    max_nor = 1
    for cycle in range(1):             #iterate thriugh all cycles range(1) by ====> range(int(len(df)/480))
        count =  '{:04}'.format(cycle)
        j = cycle * 480
        ordered_data = mkdf(df.iloc[j:j+480][i])
        csv = print_df(ordered_data)
        #Print .csv files contains matrix of each parameters by name of cycles respectively
        csv.to_csv(f'{i}/{i}{count}.csv', header=None, index=None)            
        if 'C' in i:
            min_nor = -40
            max_nor = 150
            #Applying normalization for C between [-40,+150]
            new_value3 = normalize(df['C'].iloc[j:j+480][i].values, min_val, max_val, -40, 150)
            n_cbar_kws = {"ticks":[-40,150,-20,0,25,50,75,100,125]}
            df3 = print_df(mkdf(new_value3))
        else:
            #Applying normalizayion for A,B between    [-1,+1]
            new_value1 = normalize(df['A'].iloc[j:j+480][i].values, min_val, max_val, -1, 1)
            new_value2 = normalize(df['B'].iloc[j:j+480][i].values, min_val, max_val, -1, 1)
            n_cbar_kws = {"ticks":[-1.0,-0.75,-0.50,-0.25,0.00,0.25,0.50,0.75,1.0]}
        df1 = print_df(mkdf(new_value1))
        df2 = print_df(mkdf(new_value2))    

        #Plotting parameters by using HeatMap
        plt.figure()
        sns.heatmap(df, vmin=min_nor, vmax=max_nor, cmap ='coolwarm', cbar_kws=n_cbar_kws)                             
        plt.title(i, fontsize=12, color='black', loc='left', style='italic')
        plt.axis('off')
        #Print .PNG images contains HeatMap plots of each parameters by name of cycles respectively
        plt.savefig(f'{i}/{i}{count}.png')  



        #plotting all columns ['A','B','C'] in-one-window side by side


        fig, axes = plt.subplots(nrows=1, ncols=3 , figsize=(20,10))

        plt.subplot(131)
        sns.heatmap(df1, vmin=-1, vmax=1, cmap ="coolwarm", linewidths=.75 , linecolor='black', cbar=True , cbar_kws={"ticks":[-1.0,-0.75,-0.5,-0.25,0.00,0.25,0.5,0.75,1.0]})
        fig.axes[-1].set_ylabel('[MPa]', size=20) #cbar_kws={'label': 'Celsius'}
        plt.title('A', fontsize=12, color='black', loc='left', style='italic')
        plt.axis('off')

        plt.subplot(132)
        sns.heatmap(df2, vmin=-1, vmax=1, cmap ="coolwarm", cbar=True , cbar_kws={"ticks":[-1.0,-0.75,-0.5,-0.25,0.00,0.25,0.5,0.75,1.0]})
        fig.axes[-1].set_ylabel('[Mpa]', size=20) #cbar_kws={'label': 'Celsius'}
        #sns.despine(left=True)
        plt.title('B', fontsize=12, color='black', loc='left', style='italic')
        plt.axis('off')

        plt.subplot(133)
        sns.heatmap(df3, vmin=-40, vmax=150, cmap ="coolwarm" , cbar=True , cbar_kws={"ticks":[-40,150,-20,0,25,50,75,100,125]}) 
        fig.axes[-1].set_ylabel('[°C]', size=20) #cbar_kws={'label': 'Celsius'}
        #sns.despine(left=True)
        plt.title('C', fontsize=12, color='black', loc='left', style='italic')
        plt.axis('off')


        plt.suptitle(f'Analysis of data in cycle Nr.: {count}', color='yellow', backgroundcolor='black', fontsize=48, fontweight='bold')
        plt.subplots_adjust(top=0.7, bottom=0.3, left=0.05, right=0.95, hspace=0.2, wspace=0.2)
        #plt.subplot_tool()
        plt.savefig(f'{i}/{i}{i}{count}.png') 
        plt.show()

До сих пор я не мог получить правильный вывод из-за того, что в каждом цикле он печатает график каждого из них 3 раза с разными интервалами, например. он печатает 'A' влево, затем снова печатает 'A' под именем 'B' и 'C' в середине и справа в одном окне. Снова он печатает 'B' 3 раза вместо одного раза и помещает его посередине, и в конце он печатает 'C' 3 раза вместо одного раза и помещает в правую сторону, он помещает в середину и влево!

Цель состоит в том, чтобы перехватить участки всех 3 столбцов A, B & C в одно окно для каждого цикла (каждые 480 значений по 480- значения) в главном цикле for!

1-й цикл: 0000 -----> подсюжеты A, B, C ----> Сохранить как 0000.png

2-й цикл: 0001 -----> участки A, B, C ----> Сохраните его как 0001.png ...

Проблема заключается в использовании df внутри цикла for, и он передает значения A или B или C 3 раза , в то время как он должен передавать ему значения, принадлежащие в каждом столбце один раз соответственно я предоставляю картинку неудачного вывода здесь , чтобы вы могли точно видеть, где проблема явно

мой желаемый результат ниже:

picture

Я также предоставляю образец текстового файла набора данных для 3 циклов: набор данных

1 Ответ

0 голосов
/ 23 января 2019

Итак, после просмотра вашего кода и ваших требований, я думаю, что знаю, в чем проблема. Ваши for петли находятся в неправильном порядке. Вы хотите новую цифру для каждого цикла, содержащую каждый «A», «B» и «C» в качестве вспомогательных участков.

Это означает, что ваш внешний цикл должен проходить через циклы, а затем ваш внутренний цикл по i, тогда как ваш отступ и порядок циклов заставляют вас пытаться построить все 'A','B','C' вспомогательных участков уже в вашем первом цикле через i (i='A', cycle=1), а не после первого цикла в первом цикле, со всеми i (i='A','B','C', cycle=1).

Именно поэтому у вас возникает проблема (как упоминалось в вашем комментарии к этому ответу ) о том, что вы не определяете df3. Определение df3 ist в блоке if, проверяющем, если 'C' in i, в вашем первом проходном цикле это условие не выполняется и, следовательно, df3 не определено, но вы все еще пытаетесь построить его!

Также у вас снова возникла та же проблема, что и в другом вопросе со значениями NaN / inf.

Изменение порядка циклов for, отступов и очистка значений NaN / inf приведут к следующему коду:

#...
#df contains all the data
df = pd.DataFrame(data, columns=['A','B','C'], index = id_set[:,0])  
df = df.replace(np.inf, np.nan)
df = df.fillna(0)

'''
Data generation phase

'''

#next iteration create all plots, change the number of cycles
cycles = int(len(df)/480)
print(cycles)
for cycle in range(cycles):             #iterate thriugh all cycles range(1) by ====> range(int(len(df)/480))
    count =  '{:04}'.format(cycle)
    j = cycle * 480
    for i in df:
        try:
            os.mkdir(i)
        except:
            pass

        min_val = df[i].min()
        min_nor = -1
        max_val = df[i].max()
        max_nor = 1

        ordered_data = mkdf(df.iloc[j:j+480][i])
        csv = print_df(ordered_data)
        #Print .csv files contains matrix of each parameters by name of cycles respectively
        csv.to_csv(f'{i}/{i}{count}.csv', header=None, index=None)            
        if 'C' in i:
            min_nor = -40
            max_nor = 150
            #Applying normalization for C between [-40,+150]
            new_value3 = normalize(df['C'].iloc[j:j+480], min_val, max_val, -40, 150)
            n_cbar_kws = {"ticks":[-40,150,-20,0,25,50,75,100,125]}
            df3 = print_df(mkdf(new_value3))
        else:
            #Applying normalizayion for A,B between    [-1,+1]
            new_value1 = normalize(df['A'].iloc[j:j+480], min_val, max_val, -1, 1)
            new_value2 = normalize(df['B'].iloc[j:j+480], min_val, max_val, -1, 1)
            n_cbar_kws = {"ticks":[-1.0,-0.75,-0.50,-0.25,0.00,0.25,0.50,0.75,1.0]}
            df1 = print_df(mkdf(new_value1))
            df2 = print_df(mkdf(new_value2))    

    #        #Plotting parameters by using HeatMap
    #        plt.figure()
    #        sns.heatmap(df, vmin=min_nor, vmax=max_nor, cmap ='coolwarm', cbar_kws=n_cbar_kws)                             
    #        plt.title(i, fontsize=12, color='black', loc='left', style='italic')
    #        plt.axis('off')
    #        #Print .PNG images contains HeatMap plots of each parameters by name of cycles respectively
    #        plt.savefig(f'{i}/{i}{count}.png')  


    #plotting all columns ['A','B','C'] in-one-window side by side
    fig, axes = plt.subplots(nrows=1, ncols=3 , figsize=(20,10))

    plt.subplot(131)
    sns.heatmap(df1, vmin=-1, vmax=1, cmap ="coolwarm", linewidths=.75 , linecolor='black', cbar=True , cbar_kws={"ticks":[-1.0,-0.75,-0.5,-0.25,0.00,0.25,0.5,0.75,1.0]})
    fig.axes[-1].set_ylabel('[MPa]', size=20) #cbar_kws={'label': 'Celsius'}
    plt.title('A', fontsize=12, color='black', loc='left', style='italic')
    plt.axis('off')

    plt.subplot(132)
    sns.heatmap(df2, vmin=-1, vmax=1, cmap ="coolwarm", cbar=True , cbar_kws={"ticks":[-1.0,-0.75,-0.5,-0.25,0.00,0.25,0.5,0.75,1.0]})
    fig.axes[-1].set_ylabel('[Mpa]', size=20) #cbar_kws={'label': 'Celsius'}
    #sns.despine(left=True)
    plt.title('B', fontsize=12, color='black', loc='left', style='italic')
    plt.axis('off')

    plt.subplot(133)
    sns.heatmap(df3, vmin=-40, vmax=150, cmap ="coolwarm" , cbar=True , cbar_kws={"ticks":[-40,150,-20,0,25,50,75,100,125]}) 
    fig.axes[-1].set_ylabel('[°C]', size=20) #cbar_kws={'label': 'Celsius'}
    #sns.despine(left=True)
    plt.title('C', fontsize=12, color='black', loc='left', style='italic')
    plt.axis('off')


    plt.suptitle(f'Analysis of data in cycle Nr.: {count}', color='yellow', backgroundcolor='black', fontsize=48, fontweight='bold')
    plt.subplots_adjust(top=0.7, bottom=0.3, left=0.05, right=0.95, hspace=0.2, wspace=0.2)
    #plt.subplot_tool()
    plt.savefig(f'{i}/{i}{i}{count}.png') 
    plt.show()

В результате вы получите следующие три изображения в виде трех отдельных цифр с предоставленными вами данными:

Рисунок 1 , Рисунок 2 , Рисунок 3

Вообще говоря, ваш код довольно грязный. Я понял, если вы новичок в программировании и просто хотите анализировать свои данные, вы делаете все, что работает, не важно, хороша ли она.

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

Я бы порекомендовал, если вы снова столкнетесь с такой проблемой, чтобы написать какой-то «псевдокод» со всеми циклами и попытаться подумать о том, что вы пытаетесь выполнить в каждом цикле.

...