
Question:
I'm reading out a text file with some float numbers using np.loadtxt
. This is what my numpy array looks like:
x = np.loadtxt(t2)
print(x)
array([[ 1.00000000e+00, 6.61560000e-13],
[ 2.00000000e+00, 3.05350000e-13],
[ 3.00000000e+00, 6.22240000e-13],
[ 4.00000000e+00, 3.08850000e-13],
[ 5.00000000e+00, 1.11170000e-10],
[ 6.00000000e+00, 3.82440000e-11],
[ 7.00000000e+00, 5.39160000e-11],
[ 8.00000000e+00, 1.75910000e-11],
[ 9.00000000e+00, 2.27330000e-10]])
I separate out the first column from the second by doing this:
idx, coeffs = zip(*x)
Now, I want to create a mapping of id : coeff, something like this:
mapping = dict(zip(map(int, idx), coeffs))
print(mapping)
{1: 6.6155999999999996e-13,
2: 3.0535000000000001e-13,
3: 6.2223999999999998e-13,
4: 3.0884999999999999e-13,
5: 1.1117e-10,
6: 3.8243999999999997e-11,
7: 5.3915999999999998e-11,
8: 1.7591e-11,
9: 2.2733e-10}
As you can see, precision errors have been introduced. For example, 6.61560000e-13
became 6.6155999999999996e-13
.
This is what I would like, preferrably:
{1: 6.61560000e-13,
2: 3.05350000e-13,
3: 6.22240000e-13,
4: 3.08850000e-13,
...
}
How can I do this? I am working on IPython3, if that helps.
Answer1:<a href="https://stackoverflow.com/questions/45688226/fix-precision-issues-when-displaying-floats-in-python?noredirect=1#comment78334374_45688226" rel="nofollow">Jean-François Fabre's comment</a> gave me an idea, and I tried it out. Taking into consideration Alexander's suggestion to use a dict comprehension, this worked for me:
x = np.loadtxt(t2)
mapping = {int(k) : v for k, v in x.tolist()}
print (mapping)
Output:
{1: 6.6156e-13,
2: 3.0535e-13,
3: 6.2224e-13,
4: 3.0885e-13,
5: 1.1117e-10,
6: 3.8244e-11,
7: 5.3916e-11,
8: 1.7591e-11,
9: 2.2733e-10}
The reason this works is because x
is of type np.float64
. Calling .tolist()
converts x
to a list of lists, where each element is of type double.
np.float64
and double
have different __repr__
implementations. The double
uses the <a href="http://www.ampl.com/REFS/abstracts.html#rounding" rel="nofollow">David Gay Algorithm</a> to correctly represent these floats, while numpy has a much simpler implementation (mere truncation).
Not sure about the downvote.
After entering your data, you have already 'lost precision':
x = np.array([[ 1.00000000e+00, 6.61560000e-13],
[ 2.00000000e+00, 3.05350000e-13],
[ 3.00000000e+00, 6.22240000e-13],
[ 4.00000000e+00, 3.08850000e-13],
[ 5.00000000e+00, 1.11170000e-10],
[ 6.00000000e+00, 3.82440000e-11],
[ 7.00000000e+00, 5.39160000e-11],
[ 8.00000000e+00, 1.75910000e-11],
[ 9.00000000e+00, 2.27330000e-10]])
>>> x[0, 1]
6.6155999999999996e-13
Perhaps a simple dict comprehension may be easier:
>>> {int(k): v for k, v in x}
{1: 6.6155999999999996e-13,
2: 3.0535000000000001e-13,
3: 6.2223999999999998e-13,
4: 3.0884999999999999e-13,
5: 1.1117e-10,
6: 3.8243999999999997e-11,
7: 5.3915999999999998e-11,
8: 1.7591e-11,
9: 2.2733e-10}
Answer3:Going by your method itself, you can cast your input (float) array to an int
array and then construct dictionary after zip
ing it.
In [44]: dict(zip(np.asarray(x[:,0], dtype=int).tolist(), x[:,1].tolist()))
Out[44]:
{1: 6.6156e-13,
2: 3.0535e-13,
3: 6.2224e-13,
4: 3.0885e-13,
5: 1.1117e-10,
6: 3.8244e-11,
7: 5.3916e-11,
8: 1.7591e-11,
9: 2.2733e-10}
P.S. Using Python 3.6.1 in IPython 6.1.0