Show an array in format of scientific notation - python

I would like to show my results in scientific notation (e.g., 1.2e3). My data is in array format. Is there a function like tolist() that can convert the array to float so I can use %E to format the output?
Here is my code:
import numpy as np
a=np.zeros(shape=(5,5), dtype=float)
b=a.tolist()
print a, type(a), b, type(b)
print '''%s''' % b
# what I want is
print '''%E''' % function_to_float(a or b)

If your version of Numpy is 1.7 or greater, you should be able to use the formatter option to numpy.set_printoptions. 1.6 should definitely work -- 1.5.1 may work as well.
import numpy as np
a = np.zeros(shape=(5, 5), dtype=float)
np.set_printoptions(formatter={'float': lambda x: format(x, '6.3E')})
print a
Alternatively, if you don't have formatter, you can create a new array whose values are formatted strings in the format you want. This will create an entirely new array as big as your original array, so it's not the most memory-efficient way of doing this, but it may work if you can't upgrade numpy. (I tested this and it works on numpy 1.3.0.)
To use this strategy to get something similar to above:
import numpy as np
a = np.zeros(shape=(5, 5), dtype=float)
formatting_function = np.vectorize(lambda f: format(f, '6.3E'))
print formatting_function(a)
'6.3E' is the format you want each value printed as. You can consult the this documentation for more options.
In this case, 6 is the minimum width of the printed number and 3 is the number of digits displayed after the decimal point.

You can format each of the elements of an array in scientific notation and then display them as you'd like. Lists cannot be converted to floats, they have floats inside them potentially.
import numpy as np
a = np.zeroes(shape=(5, 5), dtype=float)
for e in a.flat:
print "%E" % e
or
print ["%E" % e for e in a.flat]

Related

Convert a MATLAB matrix object to a python NumPy array

I want to call some python code from MATLAB, in order to do this I need to convert a matrix object to a NumPy ndarray, through the MATLAB function py.numpy.array. However, passing simply the matrix object to the function does not work. At the moment I solved the problem converting the matrix to a cell of cells object, containing the rows of the matrix. For example
function ndarray = convert(mat)
% This conversion fails
ndarray = py.numpy.array(mat)
% This conversion works
cstr = cell(1, size(mat, 1));
for row = 1:size(mat, 1)
cstr(row) = {mat(row, :)};
end
ndarray = py.numpy.array(cstr);
I was wondering if it exists some more efficient solution.
Assuming your array contains double values, the error tells us exactly what we should do:
A = magic(3);
%% Attempt 1:
try
npA = py.numpy.array(A);
% Result:
% Error using py.numpy.array
% Conversion of MATLAB 'double' to Python is only supported for 1-N vectors.
catch
end
%% Attempt 2:
npA = py.numpy.array(A(:).');
% Result: OK!
Then:
>> whos npA
Name Size Bytes Class Attributes
npA 1x1 8 py.numpy.ndarray
Afterwards you can use numpy.reshape to get the original shape back, either directly in MATLAB or in Python.
Actually, using python 2.7 and Matlab R2018b, it worked with simply doing:
pyvar = py.numpy.array(var);
Matlab tells me that if I want to convert the numpy array to Matlab variable, I can just use double(pyvar)
By the way, it didn't worked with python 3.7, neither using an older version of Matlab . I don't know what this means, but I thought this might be helpful

Why is numpy array's .tolist() creating long doubles?

I have some math operations that produce a numpy array of results with about 8 significant figures. When I use tolist() on my array y_axis, it creates what I assume are 32-bit numbers.
However, I wonder if this is just garbage. I assume it is garbage, but it seems intelligent enough to change the last number so that rounding makes sense.
print "y_axis:",y_axis
y_axis = y_axis.tolist()
print "y_axis:",y_axis
y_axis: [-0.99636686 0.08357361 -0.01638707]
y_axis: [-0.9963668578012771, 0.08357361233570479, -0.01638706796138937]
So my question is: if this is not garbage, does using tolist actually help in accuracy for my calculations, or is Python always using the entire number, but just not displaying it?
When you call print y_axis on a numpy array, you are getting a truncated version of the numbers that numpy is actually storing internally. The way in which it is truncated depends on how numpy's printing options are set.
>>> arr = np.array([22/7, 1/13]) # init array
>>> arr # np.array default printing
array([ 3.14285714, 0.07692308])
>>> arr[0] # int default printing
3.1428571428571428
>>> np.set_printoptions(precision=24) # increase np.array print "precision"
>>> arr # np.array high-"precision" print
array([ 3.142857142857142793701541, 0.076923076923076927347012])
>>> float.hex(arr[0]) # actual underlying representation
'0x1.9249249249249p+1'
The reason it looks like you're "gaining accuracy" when you print out the .tolist()ed form of y_axis is that by default, more digits are printed when you call print on a list than when you call print on a numpy array.
In actuality, the numbers stored internally by either a list or a numpy array should be identical (and should correspond to the last line above, generated with float.hex(arr[0])), since numpy uses numpy.float64 by default, and python float objects are also 64 bits by default.
My understanding is that numpy is not showing you the full precision to make the matrices lay out consistently. The list shouldn't have any more precision than its numpy.array counterpart:
>>> v = -0.9963668578012771
>>> a = numpy.array([v])
>>> a
array([-0.99636686])
>>> a.tolist()
[-0.9963668578012771]
>>> a[0] == v
True
>>> a.tolist()[0] == v
True

are numpy array elements rounded automatically?

I have an numpy array of floats in Python.
When I print the array, the first value is:
[7.14519700e+04, ....
If, however, I print out just the first value on it's own, the print out reads:
71451.9699799
Obviously these numbers should be identical, so I just wondered, is the array just showing me a rounded version of the element? The second number here has 12 significant figures, and the first only has 9.
I guess I just wonder why these numbers are different?
It's just in the printing, not in the storage. The only confusion might occur because the first example uses numpy's print precision settings, the second example general python's print settings.
You can adjust the numpy precision and print by
numpy.set_printoptions(precision=20)
print myarray`
(adjust precision to your needs), or select the number of significant figures in standard python formatted print:
print ('%.20f' % myarray[0])
The internal representation of the number is always the same.
The types in a numpy array are well defined. You can get how they are stored by inspecting the numpy.dtype property of an array.
For example:
import numpy
a = numpy.zeros(10)
print a.dtype
will show float64, that is a 64-bit floating point number.
You can specify the type of the array explicitly using either the commonly accepted dtype argument, or the dtype type object (that is, the thing that makes the dtype).
a = numpy.zeros(10, dtype='complex32') # a 32-bit floating point
b = numpy.longdouble(a) # create a long-double array from a
Regarding the printing, this is just a formatting issue. You can twiddle how numpy prints an array using numpy.set_printoptions:
>>> a = numpy.random.randn(3) # for interest, randn annoyingly doesn't support the dtype arg
>>> print a
[ 0.12584756 0.73540009 -0.17108244 -0.96818512]
>>> numpy.set_printoptions(precision=3)
>>> print a
[ 0.126 0.735 -0.171 -0.968]

Type casting in Python 2.7

How do I cast a float into long in Python 2.7?
I'm doing the same in Python 2.3 like this:
from array import*
data = array('L',[12.34])
print data
which prints out:
array('L',[12L])
How do I do the same in Python 2.7?
Maybe like this?
>>> long(12.34)
12L
These days, it is much more common to see numpy arrays than arrays from the array module, however, your array can be constructed as:
>>> from array import *
>>> array('L',map(long,[12.34]))
array('L', [12L])
with numpy, it could be done as:
>>> import numpy as np
>>> np.array([12.34],dtype=long)
However, this doesn't actually create python longs, it actually creates an array of np.int64 integers (8 byte ints -- Not arbitrary precision like python long).
lst = [1.1,2.2]
data = map(long,lst)

How to set the precision on str(numpy.float64)?

i need to write a couple of numpy floats to a csv-file which has additional string content. therefore i dont use savetxt etc. with numpy.set_printoptions() i can only define the print behaviour, but not the str() behaviour. i know that i miss something and it cant be that hard, but i dont find a reasonable answer on the interwebs. maybe someone can point me in the right direction. heres some example code:
In [1]: import numpy as np
In [2]: foo = np.array([1.22334])
In [3]: foo
Out[3]: array([ 1.22334])
In [4]: foo[0]
Out[4]: 1.2233400000000001
In [5]: str(foo[0])
Out[5]: '1.22334'
In [6]: np.set_printoptions(precision=3)
In [7]: foo
Out[7]: array([ 1.223])
In [8]: foo[0]
Out[8]: 1.2233400000000001
In [9]: str(foo[0])
Out[9]: '1.22334'
How do i convert np.float to a nicely formatted string, which i can feed to file.write()?
kind regards,
fookatchu
You can just use standard string formatting:
>>> x = 1.2345678
>>> '%.2f' % x
'1.23'
You could use normal String formating, see:
http://docs.python.org/library/string.html#formatspec
Example:
print '{:.2f}'.format(0.1234) # '0.12'
print '{:.2e}'.format(0.1234) # '1.23e-01'
Numpy 1.14 and later have format_float_positional and format_float_scientific functions to format a floating-point scalar as a decimal string in positional or scientific notation, with control over rounding, trimming and padding. These functions offer much more control to the formatting than conventional Python string formatters.
import numpy as np
x = np.float64('1.2345678')
print(np.format_float_positional(x)) # 1.2345678
print(np.format_float_positional(x, precision=3)) # 1.235
print(np.format_float_positional(np.float16(x))) # 1.234
print(np.format_float_positional(np.float16(x), unique=False, precision=8)) # 1.23437500
y = x / 1e8
print(np.format_float_scientific(y)) # 1.2345678e-08
print(np.format_float_scientific(y, precision=3, exp_digits=1)) # 1.235e-8
etc.
These advanced formatters are based on the Dragon4 algorithm; see Ryan Juckett's Printing Floating-Point Numbers to read more on the subject.
Instead of str(foo[0]), use "%.3f" % foo[0].
Also you can do:
precision = 2
str(np.round(foo[0], precision))
It had some advantages for me over the ('%.2f' % x) when I needed to do string a str(np.log(0.0)) which is neatly treated to "-inf" by numpy so you don't have to bother here.

Categories