8

Here is my code snippets. It prints the means and the standard deviations from the image pixels.

from numpy import asarray
from PIL import Image
import os

os.chdir("../images") 
image = Image.open("dubai_2020.jpg")
pixels = asarray(image) 
pixels = pixels.astype("float32")
means, stds = pixels.mean(axis=(0, 1), dtype="float64"), pixels.std(
    axis=(0, 1), dtype="float64")
print(f"Means: {means:%.2f}, Stds: {stds:%.2f} ")

And the output is

 File "pil_local_standard5.py", line 15, in <module>
    print(f"Means: {means:%.2f, %.2f, %.2f}, Stds: {stds:%.2f, %.2f, %.2f} ")

TypeError: unsupported format string passed to numpy.ndarray.__format__

How do I define the f-strings format of the data in this case?

hpaulj
  • 221,503
  • 14
  • 230
  • 353
passion
  • 387
  • 4
  • 16
  • `numpy` uses its own formatting specifications. The Python ones, whether '%', 'str.format' or 'f' don't work within an array. `f{x!s}` and `f{x!r}` work, but not much else. Oh, and '%.2f' isn't right. Use the `str.format` style, e.g. `f'{12.23:.2f}' ` – hpaulj Feb 13 '20 at 06:04
  • @hpaulj Thank you for your comment. But your suggestion like f'{12.23:.2f}' works only for the scalar or the non-array. My case is the f-string for the Numpy array. And your suggestion was tried and found not working. You may try my snippets by yourself then you can find it out. – passion Feb 13 '20 at 13:25
  • The 'oh and' means I'm bringing up a different point. I'm not saying that will work with arrays. – hpaulj Feb 13 '20 at 14:16
  • @hpaulj, You're right! I misunderstood your comments. Sorry for that. – passion Feb 14 '20 at 10:19

2 Answers2

6

I think the easiest way to accomplish something similar to what you want, currently would require the use of numpy.array2string.

For example, let's say means = np.random.random((5, 3)). Then you could do this:

import numpy as np
means = np.random.random((5, 3)).astype(np.float32)  # simulate some array
print(f"{np.array2string(means, precision=2, floatmode='fixed')}")

which will print:

[[0.41 0.12 0.84]
 [0.28 0.43 0.29]
 [0.68 0.41 0.14]
 [0.75 1.00 0.16]
 [0.30 0.49 0.37]]

The same can be achieved with:

print(f"{np.array2string(means, formatter={'float': lambda x: f'{x:.2f}'})}")

You can also add separators, if you wish:

print(f"{np.array2string(means, formatter={'float': lambda x: f'{x:.2f}'}, separator=', ')}")

which would print:

[[0.41, 0.12, 0.84],
 [0.28, 0.43, 0.29],
 [0.68, 0.41, 0.14],
 [0.75, 1.00, 0.16],
 [0.30, 0.49, 0.37]]
AGN Gazer
  • 8,025
  • 2
  • 27
  • 45
1

Unfortunately, Python's f-string doesn't support formatting of numpy arrays.


A workaround I came up with:

def prettifyStr(numpyArray, fstringText):
  num_rows = numpyArray.ndim
  l = len(str(numpyArray))
  t = (l // num_rows)
  diff_to_center_align = 50 - t
  return f"{str(numpyArray)}{' ': <{diff_to_center_align}}{fstringText}"

Sample use

    print( prettifyStr(a2, "this is some text") )
    print( prettifyStr(a3, "this is some text") )
    print( prettifyStr(a1, "this is some text") )
    print( prettifyStr(a4, "this is some text") )

Output

[[0.  3.  4. ]
 [0.  5.  5.1]]                                   this is some text 

[[0.   3.   4.   4.35]
 [0.   5.   5.1  3.6 ]]                           this is some text 

[[0 3]
 [0 5]]                                           this is some text 

[[0.   3.   4.   4.35 4.25]
 [0.   5.   5.1  3.6  3.1 ]]                      this is some text
Sebastian Nielsen
  • 3,835
  • 5
  • 27
  • 43