Gráficos agrupados de varios colores y barras

Gráficos agrupados de varios colores y barras

Tengo una secuencia de comandos Python que genera automáticamente códigos LaTeX que trazan gráficos de barras. Un ejemplo del código generado es el siguiente:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{width=7cm,compat=1.8}
\usepackage{pgfplotstable}
\renewcommand*{\familydefault}{\sfdefault}
\usepackage{sfmath}
\begin{document}
\begin{tikzpicture}
  \centering
  \begin{axis}[
        ybar, axis on top,
        title={Performance charts},
        height=8cm, width=15.5cm,
        bar width=1.5cm,
        ymajorgrids, tick align=inside,
        major grid style={draw=white},
        enlarge y limits={value=.1,upper},
        ymin=0, ymax=0.01,
        axis x line*=bottom,
        axis y line*=right,
        y axis line style={opacity=0},
        tickwidth=0pt,
        enlarge x limits=true,
        legend style={
            at={(0.5,-0.2)},
            anchor=north,
            legend columns=-1,
            /tikz/every even column/.append style={column sep=0.5cm}
        },
        ylabel={Time (seconds)},
        symbolic x coords={
           10,
           20,
       },
       xtick=data,
       nodes near coords={
        \pgfmathprintnumber[precision=3]{\pgfplotspointmeta}
       }
    ]
    \addplot+[ybar, fill=blue!50] plot coordinates {
      (10, 0.001223850250244141)
      (20, 0.001497483253479004)
    };
    \addplot+[ybar, fill=blue!25] plot coordinates {
      (10, 0.00045402050018310557)
      (20, 0.001987481117248536)
    };
    \addplot+[ybar, fill=red!50] plot coordinates {
      (10, 0.0008006999999999999)
      (20, 0.0010588)
    };
    \addplot+[ybar, fill=red!25] plot coordinates {
      (10, 0.0002661999999999997)
      (20, 0.0012075)
    };
    \legend{Real Time (Loading), Real-Time (Querying), CPU Time (Loading), CPU Time (Querying)}
  \end{axis}
\end{tikzpicture}
\end{document}

Produjo este gráfico:Trama actual

Sin embargo, quiero que las dos barras en tiempo real estén apiladas sobre sí mismas. Lo mismo que los tiempos de CPU. De modo que haya dos barras por coordenada x. El código Python que generó este código látex es:

def generate_latex_files(data, env_name, output_dir: Path) -> None:
    for key, values in data.items():
        if key[0] == env_name:
            # Sort values by graph size
            values.sort(key=lambda x: x[0])

            # Calculate maximum value for ymax
            max_value = max(sum(val['loading'] + val['querying']) for _, val in values) * 1.1

            file_name = f'{key[1]}_{key[2]}.tex'
            full_file_name = output_dir / env_name / file_name
            full_file_name.parent.mkdir(exist_ok=True, parents=True)
            with open(full_file_name, 'w') as f:
                f.write('\\documentclass[border=10pt]{standalone}\n')
                f.write('\\usepackage{pgfplots}\n')
                f.write('\\pgfplotsset{width=7cm,compat=1.8}\n')
                f.write('\\usepackage{pgfplotstable}\n')
                f.write('\\renewcommand*{\\familydefault}{\\sfdefault}\n')
                f.write('\\usepackage{sfmath}\n')
                f.write('\\begin{document}\n')
                f.write('\\begin{tikzpicture}\n')
                f.write('  \\centering\n')
                f.write('  \\begin{axis}[\n')
                f.write('        ybar, axis on top,\n')
                f.write(f'        title={{Performance charts}},\n')
                f.write('        height=8cm, width=15.5cm,\n')
                f.write('        bar width=1.5cm,\n')
                f.write('        ymajorgrids, tick align=inside,\n')
                f.write('        major grid style={draw=white},\n')
                f.write('        enlarge y limits={value=.1,upper},\n')
                f.write(f'        ymin=0, ymax={max_value:.2f},\n')
                f.write('        axis x line*=bottom,\n')
                f.write('        axis y line*=right,\n')
                f.write('        y axis line style={opacity=0},\n')
                f.write('        tickwidth=0pt,\n')
                f.write('        enlarge x limits=true,\n')
                f.write('        legend style={\n')
                f.write('            at={(0.5,-0.2)},\n')
                f.write('            anchor=north,\n')
                f.write('            legend columns=-1,\n')
                f.write('            /tikz/every even column/.append style={column sep=0.5cm}\n')
                f.write('        },\n')
                f.write('        ylabel={Time (seconds)},\n')
                f.write('        symbolic x coords={\n')
                for value in values:
                    f.write(f'           {value[0]},\n')
                f.write('       },\n')
                f.write('       xtick=data,\n')
                f.write('       nodes near coords={\n')
                f.write('        \\pgfmathprintnumber[precision=3]{\\pgfplotspointmeta}\n')
                f.write('       }\n')
                f.write('    ]\n')

                # Real time plots
                f.write('    \\addplot+[ybar, fill=blue!50] plot coordinates {\n')
                for value in values:
                    f.write(f'      ({value[0]}, {value[1]["loading"][0]})\n')
                f.write('    };\n')
                f.write('    \\addplot+[ybar, fill=blue!25] plot coordinates {\n')
                for value in values:
                    f.write(f'      ({value[0]}, {value[1]["querying"][0]})\n')
                f.write('    };\n')

                # CPU time plots
                f.write('    \\addplot+[ybar, fill=red!50] plot coordinates {\n')
                for value in values:
                    f.write(f'      ({value[0]}, {value[1]["loading"][1]})\n')
                f.write('    };\n')
                f.write('    \\addplot+[ybar, fill=red!25] plot coordinates {\n')
                for value in values:
                    f.write(f'      ({value[0]}, {value[1]["querying"][1]})\n')
                f.write('    };\n')

                f.write('    \\legend{Real-Time (Loading), Real-Time (Querying), CPU Time (Loading), CPU Time (Querying)}\n')
                f.write('  \\end{axis}\n')
                f.write('\\end{tikzpicture}\n')
                f.write('\\end{document}\n')

Los datos objeto de tratamiento tienen esta estructura:

{
   (<env_name>, <graph_type>, <mode>): [(<graph_size>, {'loading': (<real_time>, <cpu_time>), 'querying': (<real_time>, <cpu_time>)}),...]
}

¿Hay alguna manera de lograr esto? Solo he podido apilar todas las veces con una barra.

Actualizar:Quiero que los datos en tiempo real se apilen (cargando en la parte inferior, consultando en la parte superior). Lo mismo se aplica al tiempo de CPU como se muestra en este boceto.

Boceto de la trama deseada.

Respuesta1

Parece que requiere algún esfuerzo colocar dos gráficos de barras apiladas uno al lado del otro. Ver por ejemploesta solución de Jakeoeso de tom bombadil.

Entonces, a menos que desee dedicar este esfuerzo y tiempo a la depuración, le sugiero simplemente dibujar dos diagramas de la misma fuente de datos.Para aquellos interesados, este cambio de concepto sigue los patrones de los Principios Inventivos de hacer un poco menos, al menos hacer una copia.

Algunas observaciones.

Archivo de datos

Asumo una estructura de datos como esta:

 \begin{filecontents}{data2.dat}
 time  lrt lct  qrt qct
 10     5   4   3   3
 20     7   5   4   3
 30     4   7   5   2
 \end{filecontents}

Aquí los datos simplemente se incluyen en el archivo .tex, mientras que usted puede tener simplemente data3.datetc en su directorio y cargarlo, consulte a continuación.

Supongo que las dos primeras columnas van juntas, al igual que las dos últimas. Si eso está mal, simplemente cambie las y=asignaciones a continuación.

\addplot-s

Trazar columna por columna, por ejemplo, aquí la segunda llamada lrt. reemplace los nombres de archivo con el suyo. Dígale al programa que los datos contienen un encabezado.

    \addplot table[header=true,x=time,y=lrt]{data2.dat};% i.e. your data file

eje

Solo como demostración, si su título contiene una coma, coloque todo dentro de { }. Se necesitan las dos declaraciones de barra. Pon etiquetas útiles. Las entradas de la leyenda son simplemente tontas: use mejores nombres.

   \begin{axis}[
        title={Real-time data, Load},   
        ybar stacked,
        stack plots=y,
        xmin=0, xmax=50,
        xlabel=time (s),
        ylabel=percent,
        legend entries={lrt, lct},% replace by better names
    ]

Mejoras sugeridas más adelante

  • mueva el nombre de su archivo de datos a \newcommand, reemplácelo en \addplots, para cambiarlo en un solo lugar
  • cambiar los esquemas de color para ambas parcelas (ver manual)
  • mover la leyenda, por ejemplo, afuera (ver manual)
  • ajuste el ancho y alto de los diagramas a sus necesidades
  • ponlos en una articleclase o similar, si te conviene; independiente solo crea 2 imágenes (consulte su manual)
  • encontrar manuales en ctan, por ejemplo, mediante términos de búsqueda en su motor de búsquedactan pgfplots
  • asegúrese de que sus intervalos de tiempo no cambien para evitar una visualización incorrecta de los datos

resultado

\documentclass[10pt,border=3mm,tikz]{standalone}
\usepackage{pgfplots}

\begin{document}
 % ~~~ pretending you have said file in your directory
 %     assuming lrt= load real timeetc.
 %     assuming, this is your data structure

 \begin{filecontents}{data2.dat}
 time  lrt lct  qrt qct
 10     5   4   3   3
 20     7   5   4   3
 30     4   7   5   2
 \end{filecontents}

 % ~~~ Concept: Draw two diagrams
 \begin{tikzpicture}    % LOAD
   \begin{axis}[
        title={Real-time data, Load},   
        ybar stacked,
        stack plots=y,
        xmin=0, xmax=50,
        xlabel=time (s),
        ylabel=percent,
        legend entries={lrt, lct},% replace by better names
    ]
    \addplot table[header=true,x=time,y=lrt]{data2.dat};% i.e. your data file
    \addplot table[header=true,x=time,y=lct]{data2.dat};    
   \end{axis}
 \end{tikzpicture}
 
 % ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 \begin{tikzpicture}    % CPU
   \begin{axis}[
        title={Real-time data, CPU},    
        ybar stacked,
        stack plots=y,
        xmin=0, xmax=50,
        xlabel=time (s),
        ylabel=percent,
        legend entries={qrt,qct},
    ]
    \addplot table[header=true,x=time,y=qrt]{data2.dat};
    \addplot table[header=true,x=time,y=qct]{data2.dat};
    
   \end{axis}
 \end{tikzpicture}

\end{document}

Respuesta2

respuesta MS-SPOme señaló aLa solución de Jakeque se utilizó para generar este código de látex:

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\makeatletter
\newcommand\resetstackedplots{
   \pgfplots@stacked@isfirstplottrue
   \addplot [forget plot,draw=none] coordinates{(10,0) (20,0)};
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
   ybar stacked,
   title={Performance charts},
   height=0.019\textheight, width=1.5\textwidth,
   bar width=0.8cm,
   ymajorgrids, tick align=inside,
   major grid style={draw=gray!20},
   xtick=data,
   ymin=0,
   axis x line*=bottom,
   axis y line*=left,
   enlarge x limits=0.4,
   legend entries={
       Real Time (Loading),
       Real Time (Querying),
       CPU Time (Loading),
       CPU Time (Querying),
   },
   legend style={
       at={(0.5,-0.2)},
       anchor=north,
       legend columns=-1,
   },
   ylabel={Time (seconds)},
   xlabel={Graph Size},
   symbolic x coords={
           10,
           20,
       },
]
\addplot +[bar shift=-.5cm] coordinates {
    (10, 0.001223850250244141)
    (20, 0.001497483253479004)
};
\addplot +[bar shift=-.5cm] coordinates {
    (10, 0.00045402050018310557)
    (20, 0.001987481117248536)
};
\resetstackedplots
\addplot +[bar shift=.5cm] coordinates {
    (10, 0.0008006999999999999)
    (20, 0.0010588)
};
\addplot +[bar shift=.5cm] coordinates {
    (10, 0.0002661999999999997)
    (20, 0.0012075)
};
\end{axis}
\end{tikzpicture}
\end{document}

El código produjo este gráfico:

El gráfico

Fue generado dinámicamente por estefunción de pitón.

información relacionada