1

I create a comparison between two pandas dataframes and print-out the output in terminal, like following:

for key in raw.keys():
    if key == 'jao_atc':
        comparison[key] = raw[key].reindex(data.hourly_index,
                                           fill_value='----')\
            .compare(processed[key], keep_equal=True)
print(comparison['jao_atc'])

The output is:

                          DEtoDK         DKtoDE        
                            self   other   self   other
2021-03-28 23:00:00+00:00   ----  2500.0   ----  1900.0
2021-03-29 01:00:00+00:00   2500  2500.0   1900  1890.0
2021-03-29 04:00:00+00:00   2500  2500.0   1890  1900.0
2021-03-29 05:00:00+00:00   2500  2500.0   1900  1860.0
2021-03-29 07:00:00+00:00   2500  2500.0   1860  1870.0
...                          ...     ...    ...     ...
2021-05-31 19:00:00+00:00   1830  2200.0   2470  2500.0
2021-05-31 20:00:00+00:00   2200  2280.0   2500  2500.0
2021-05-31 21:00:00+00:00   2280  2500.0   2500  2360.0
2021-05-31 22:00:00+00:00   2500  2500.0   2360  2170.0
2021-05-31 23:00:00+00:00   2500     NaN   2170     NaN
[1159 rows x 4 columns]

I would like to generate an image from this output, however I do not want to take screenshot of the terminal, instead I am looking for a function like create_image_of_the_print_function(comparison['jao_atc']), which will create an image of the terminal output.

Is this possible? how?

This Export a Pandas dataframe as a table image works for the dataframes. Is there more generic applicable solution for all the outputs?

Expected Result:

image(print(comparison['jao_atc'))

enter image description here


with text-to-image, since I have to use string dataframe converted to_string() which removes the nice format of terminal output:

enter image description here

oakca
  • 1,408
  • 1
  • 18
  • 40

2 Answers2

0

So there are a few solutions that are possible to fill in your requirement here, generally you have a text and you would want to export it into an image in some format. The two suggestions I have in mind are:

1- Using the PIL library (more info on Add Text on Image using PIL)

2- Using openCV library (Info on https://docs.opencv.org/3.4/dc/da5/tutorial_py_drawing_functions.html)

Both those libraries will need you to manually setup the image (e.g. the starting location, width-height-fonts,etc). But you can get the results as you need it exactly.

Edit: This is a library based on PIL that might do exactly what you need:

https://pypi.org/project/text-to-image/

And its usage is as follows:

import text_to_image

encoded_image_path = text_to_image.encode(stringObject, imageLocation)

Edit 2:

Another method is by using the dataframe_image module, which would convert the pandas dataframe directly into an image.

Zaid Al Shattle
  • 1,454
  • 1
  • 12
  • 21
  • Well, I was looking more like `import os`, and then `os.terminal_output_image(print(...))`, so that I could use it wherever I want. – oakca Jul 16 '21 at 13:57
  • I can look for another library that does that. give me a few minutes – Zaid Al Shattle Jul 16 '21 at 13:58
  • However, worth noting is if you want to use PIL, you can create a short function (5-10 lines max) that can do the "terminal_output_image". It is not a premade function but perhaps I can make you a sample code for it soon. But an example is here: https://code-maven.com/create-images-with-python-pil-pillow – Zaid Al Shattle Jul 16 '21 at 13:59
  • EDIT: does this function do what you need? https://pypi.org/project/text-to-image/ Edit2: Edited answer with more info – Zaid Al Shattle Jul 16 '21 at 14:04
  • Almost!, the only problem is when I convert the df to string, it is not readible anymore however text_to_image creates the picture though :)), I ll accept your answer soon bro, u tried enough to help me. TY! – oakca Jul 16 '21 at 14:11
  • Can you show me/edit the question with the current output you are getting? Is the whole text encoded incorrectly, or is it the formatting? – Zaid Al Shattle Jul 16 '21 at 14:12
  • It is just a black/gray picture around 10cm x 10cm, since the df has 3000+ rows when converted to string, nothing can be read anymore. And also `df.to_string()` removes the nice formatting of the terminal output... – oakca Jul 16 '21 at 14:15
  • If the string isn't suitable, it will need some custom function. I can try to make a custom function, but it will be in some hours because I am home. Because most preset functions will require a string (I will keep looking for a bit if a function fits you need on my way back!) @oakca – Zaid Al Shattle Jul 16 '21 at 14:19
  • I think I will go with `dataframe_image`, your answer is also accepted. But please add `dataframe_image` module to your answer! – oakca Jul 16 '21 at 14:22
0

As you had asked for a generic solution, you can get a string representation of a python object first.

For example,

df = pd.DataFrame({"Customer 1" : ["A","B","C","D","E"],
                  "Customer 2" : ["B","C","D","E","F"],
                  "Customer 3" : ["C","D","E","F","G"]})

String representation will look like (i.e. str(df)):

  Customer 1 Customer 2 Customer 3
0          A          B          C
1          B          C          D
2          C          D          E
3          D          E          F
4          E          F          G

Now to convert a text to image follow as in this answer.

Output image of the dataframe:

String to image

Code with slight modification of the referenced answer:

import PIL
import PIL.Image
import PIL.ImageFont
import PIL.ImageOps
import PIL.ImageDraw
import pandas as pd

PIXEL_ON = 0  # PIL color to use for "on"
PIXEL_OFF = 255  # PIL color to use for "off"

def text_image(text, font_path=None):
    """Convert text to a grayscale image with black characters on a white background.
    arguments:
    text_path - the content of this file will be converted to an image
    font_path - path to a font file (for example impact.ttf)
    """
    grayscale = 'L'
    # parse the file into lines
    lines = tuple(l.rstrip() for l in text.splitlines())
    # choose a font (you can see more detail in my library on github)
    large_font = 40  # get better resolution with larger size
    font_path = font_path or 'cour.ttf'  # Courier New. works in windows. linux may need more explicit path
    try:
        font = PIL.ImageFont.truetype(font_path, size=large_font)
    except IOError:
        font = PIL.ImageFont.load_default()
        print('Could not use chosen font. Using default.')
    # make the background image based on the combination of font and lines
    pt2px = lambda pt: int(round(pt * 96.0 / 72))  # convert points to pixels
    max_width_line = max(lines, key=lambda s: font.getsize(s)[0])
    # max height is adjusted down because it's too large visually for spacing
    test_string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    max_height = pt2px(font.getsize(test_string)[1])
    max_width = pt2px(font.getsize(max_width_line)[0])
    height = max_height * len(lines)  # perfect or a little oversized
    width = int(round(max_width + 40))  # a little oversized
    image = PIL.Image.new(grayscale, (width, height), color=PIXEL_OFF)
    draw = PIL.ImageDraw.Draw(image)
    # draw each line of text
    vertical_position = 5
    horizontal_position = 5
    line_spacing = int(round(max_height * 0.8))  # reduced spacing seems better
    for line in lines:
        draw.text((horizontal_position, vertical_position),
                  line, fill=PIXEL_ON, font=font)
        vertical_position += line_spacing
    # crop the text
    c_box = PIL.ImageOps.invert(image).getbbox()
    image = image.crop(c_box)
    return image

def main():
    df = pd.DataFrame({"Customer 1" : ["A","B","C","D","E"],
                    "Customer 2" : ["B","C","D","E","F"],
                    "Customer 3" : ["C","D","E","F","G"]})
    image = text_image(str(df))
    image.show()
    image.save("test.png")

if __name__ == '__main__':
    main()

Reference: Converting a .txt file to an image in Python

รยקคгรђשค
  • 1,919
  • 1
  • 10
  • 18