mac - python data to latex table
Imprimir listas como datos tabulares (12)
Actualizando la respuesta de Sven Marnach para trabajar en Python 3.4:
row_format ="{:>15}" * (len(teams_list) + 1)
print(row_format.format("", *teams_list))
for team, row in zip(teams_list, data):
print(row_format.format(team, *row))
Soy bastante nuevo en Python y ahora estoy luchando con el formato de mis datos para la salida impresa.
Tengo una lista que se usa para dos encabezados y una matriz que debe ser el contenido de la tabla. Al igual que:
teams_list = ["Man Utd", "Man City", "T Hotspur"]
data = np.array([[1, 2, 1],
[0, 1, 0],
[2, 4, 2]])
Tenga en cuenta que los nombres de los encabezados no son necesariamente de la misma longitud. Sin embargo, las entradas de datos son todos enteros.
Ahora, quiero representar esto en un formato de tabla, algo como esto:
Man Utd Man City T Hotspur
Man Utd 1 0 0
Man City 1 1 0
T Hotspur 0 1 2
Tengo el presentimiento de que debe haber una estructura de datos para esto, pero no puedo encontrarla. He intentado usar un diccionario y formatear la impresión, he intentado hacer bucles con sangría y he intentado imprimir como cadenas.
Estoy seguro de que debe haber una forma muy simple de hacer esto, pero probablemente me esté perdiendo debido a la falta de experiencia.
Algún código ad hoc para Python 2.7:
row_format ="{:>15}" * (len(teams_list) + 1)
print row_format.format("", *teams_list)
for team, row in zip(teams_list, data):
print row_format.format(team, *row)
Esto se basa en str.format()
y el Mini-Idioma de especificación de formato .
Creo que this es lo que estás buscando.
Es un módulo simple que solo calcula el ancho máximo requerido para las entradas de la tabla y luego solo usa rjust y ljust para hacer una impresión bonita de los datos.
Si desea que su rumbo izquierdo esté alineado, solo cambie esta llamada:
print >> out, row[0].ljust(col_paddings[0] + 1),
De la línea 53 con:
print >> out, row[0].rjust(col_paddings[0] + 1),
Cuando hago esto, me gusta tener cierto control sobre los detalles de cómo se formatea la tabla. En particular, quiero que las celdas de encabezado tengan un formato diferente a las celdas del cuerpo, y que los anchos de columna de la tabla sean tan anchos como sea necesario para cada una. Aquí está mi solución:
def format_matrix(header, matrix,
top_format, left_format, cell_format, row_delim, col_delim):
table = [[''''] + header] + [[name] + row for name, row in zip(header, matrix)]
table_format = [[''{:^{}}''] + len(header) * [top_format]] /
+ len(matrix) * [[left_format] + len(header) * [cell_format]]
col_widths = [max(
len(format.format(cell, 0))
for format, cell in zip(col_format, col))
for col_format, col in zip(zip(*table_format), zip(*table))]
return row_delim.join(
col_delim.join(
format.format(cell, width)
for format, cell, width in zip(row_format, row, col_widths))
for row_format, row in zip(table_format, table))
print format_matrix([''Man Utd'', ''Man City'', ''T Hotspur'', ''Really Long Column''],
[[1, 2, 1, -1], [0, 1, 0, 5], [2, 4, 2, 2], [0, 1, 0, 6]],
''{:^{}}'', ''{:<{}}'', ''{:>{}.3f}'', ''/n'', '' | '')
Aquí está la salida:
| Man Utd | Man City | T Hotspur | Really Long Column
Man Utd | 1.000 | 2.000 | 1.000 | -1.000
Man City | 0.000 | 1.000 | 0.000 | 5.000
T Hotspur | 2.000 | 4.000 | 2.000 | 2.000
Really Long Column | 0.000 | 1.000 | 0.000 | 6.000
Hay algunos paquetes de Python ligeros y útiles para este propósito:
1. tabular : https://pypi.python.org/pypi/tabulate
>>> from tabulate import tabulate
>>> print tabulate([[''Alice'', 24], [''Bob'', 19]], headers=[''Name'', ''Age''])
Name Age
------ -----
Alice 24
Bob 19
tabular tiene muchas opciones para especificar encabezados y formato de tabla.
>>> print tabulate([[''Alice'', 24], [''Bob'', 19]], headers=[''Name'', ''Age''], tablefmt=''orgtbl'')
| Name | Age |
|--------+-------|
| Alice | 24 |
| Bob | 19 |
2. PrettyTable : https://pypi.python.org/pypi/PrettyTable
>>> from prettytable import PrettyTable
>>> t = PrettyTable([''Name'', ''Age''])
>>> t.add_row([''Alice'', 24])
>>> t.add_row([''Bob'', 19])
>>> print t
+-------+-----+
| Name | Age |
+-------+-----+
| Alice | 24 |
| Bob | 19 |
+-------+-----+
PrettyTable tiene opciones para leer datos de csv, html, base de datos sql. También puede seleccionar subconjuntos de datos, ordenar tablas y cambiar estilos de tablas.
3. mesa de texto : https://pypi.python.org/pypi/texttable
>>> from texttable import Texttable
>>> t = Texttable()
>>> t.add_rows([[''Name'', ''Age''], [''Alice'', 24], [''Bob'', 19]])
>>> print t.draw()
+-------+-----+
| Name | Age |
+=======+=====+
| Alice | 24 |
+-------+-----+
| Bob | 19 |
+-------+-----+
Con Texttable puede controlar la alineación horizontal / vertical, el estilo de borde y los tipos de datos.
Otras opciones:
- terminaltables Dibuje fácilmente tablas en aplicaciones de terminal / consola de una lista de listas de cadenas. Soporta filas multilínea.
- asciitable Asciitable puede leer y escribir una amplia gama de formatos de tablas ASCII a través de las clases de lectores de extensión incorporadas.
Intentaría recorrer la lista y utilizar un formateador CSV para representar los datos que desea.
Puede especificar tabulaciones, comas o cualquier otro carácter como delimitador.
De lo contrario, recorra la lista e imprima "/ t" después de cada elemento
La siguiente función creará la tabla solicitada (con o sin número) con Python 3 (quizás también Python 2). He elegido establecer el ancho de cada columna para que coincida con el nombre del equipo más largo. Puede modificarlo si desea usar la longitud del nombre del equipo para cada columna, pero será más complicado.
Nota: Para un equivalente directo en Python 2, puede reemplazar el zip
con izip de itertools.
def print_results_table(data, teams_list):
str_l = max(len(t) for t in teams_list)
print(" ".join([''{:>{length}s}''.format(t, length = str_l) for t in [" "] + teams_list]))
for t, row in zip(teams_list, data):
print(" ".join([''{:>{length}s}''.format(str(x), length = str_l) for x in [t] + row]))
teams_list = ["Man Utd", "Man City", "T Hotspur"]
data = [[1, 2, 1],
[0, 1, 0],
[2, 4, 2]]
print_results_table(data, teams_list)
Esto producirá la siguiente tabla:
Man Utd Man City T Hotspur
Man Utd 1 2 1
Man City 0 1 0
T Hotspur 2 4 2
Si desea tener separadores de línea vertical, puede reemplazar " ".join
con " | ".join
.
Referencias:
- mucho sobre el formato https://pyformat.info/ (estilos de formato antiguos y nuevos)
- El tutorial oficial de Python (bastante bueno) - https://docs.python.org/3/tutorial/inputoutput.html#the-string-format-method
- información oficial de Python (puede ser difícil de leer) - https://docs.python.org/3/library/string.html#string-formatting
- Otro recurso: https://www.python-course.eu/python3_formatted_output.php
Pure Python 3
def print_table(data, cols, wide):
''''''Prints formatted data on columns of given width.''''''
n, r = divmod(len(data), cols)
pat = ''{{:{}}}''.format(wide)
line = ''/n''.join(pat * cols for _ in range(n))
last_line = pat * r
print(line.format(*data))
print(last_line.format(*data[n*cols:]))
data = [str(i) for i in range(27)]
print_table(data, 6, 12)
Imprimirá
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
18 19 20 21 22 23
24 25 26
Python en realidad lo hace bastante fácil.
Algo como
for i in range(10):
print ''%-12i%-12i'' % (10 ** i, 20 ** i)
tendrá la salida
1 1
10 20
100 400
1000 8000
10000 160000
100000 3200000
1000000 64000000
10000000 1280000000
100000000 25600000000
1000000000 512000000000
El% dentro de la cadena es esencialmente un carácter de escape y los caracteres siguientes le dicen a python qué tipo de formato deben tener los datos. El% fuera y después de la cadena le dice a Python que tiene la intención de usar la cadena anterior como la cadena de formato y que los siguientes datos deben colocarse en el formato especificado.
En este caso usé "% -12i" dos veces. Para desglosar cada parte:
''-'' (left align)
''12'' (how much space to be given to this part of the output)
''i'' (we are printing an integer)
De los documentos: https://docs.python.org/2/library/stdtypes.html#string-formatting
Una forma sencilla de hacer esto es recorrer todas las columnas, medir su ancho, crear una plantilla de fila para ese ancho máximo y luego imprimir las filas. No es exactamente lo que estás buscando , porque en este caso, primero debes poner tus encabezados dentro de la tabla, pero creo que podría ser útil para otra persona.
table = [
["", "Man Utd", "Man City", "T Hotspur"],
["Man Utd", 1, 0, 0],
["Man City", 1, 1, 0],
["T Hotspur", 0, 1, 2],
]
def print_table(table):
longest_cols = [
(max([len(str(row[i])) for row in table]) + 3)
for i in range(len(table[0]))
]
row_format = "".join(["{:>" + str(longest_col) + "}" for longest_col in longest_cols])
for row in table:
print(row_format.format(*row))
Lo usas así:
>>> print_table(table)
Man Utd Man City T Hotspur
Man Utd 1 0 0
Man City 1 1 0
T Hotspur 0 1 2
BeautifulTable y https://pypi.python.org/pypi/tabulate son algunos de los muchos paquetes que puede usar para resolver su problema.
Aquí hay un ejemplo de la documentation de beautifultable.
>>> from beautifultable import BeautifulTable
>>> table = BeautifulTable()
>>> table.column_headers = ["name", "rank", "gender"]
>>> table.append_row(["Jacob", 1, "boy"])
>>> table.append_row(["Isabella", 1, "girl"])
>>> table.append_row(["Ethan", 2, "boy"])
>>> table.append_row(["Sophia", 2, "girl"])
>>> table.append_row(["Michael", 3, "boy"])
>>> print(table)
+----------+------+--------+
| name | rank | gender |
+----------+------+--------+
| Jacob | 1 | boy |
+----------+------+--------+
| Isabella | 1 | girl |
+----------+------+--------+
| Ethan | 2 | boy |
+----------+------+--------+
| Sophia | 2 | girl |
+----------+------+--------+
| Michael | 3 | boy |
+----------+------+--------+
>>> import pandas
>>> pandas.DataFrame(data, teams_list, teams_list)
Man Utd Man City T Hotspur
Man Utd 1 2 1
Man City 0 1 0
T Hotspur 2 4 2