Numerically append binary numbers in np.array - python

Considering the following example array :
a = np.array([0,1,1,0,1,1,1,0,1,0])
Which could be of any dtype (int, float...)
How would I get the following output without using nasty loops and string casts ?
np.array([0b01,0b10,0b11,0b10,0b10])

a = a.astype(int)
output = a[0::2] * 2 + a[1::2]
Gives the array you've described (though it doesn't print in binary).

Related

Inferring the numeric type (exact or inexact) of an array of strings?

Suppose I've got an array of strings and I know that they are numbers but don't know whether they are intish or floatish. If I knew, I could simply convert using .astype(int) or .astype(float). What is a good (readable, performant, ideally not involving off the cuff regular expressions) way of finding out? Is there some Python or numpy machinery one could hijack?
One thing you could certainly do is parse them all as floats, since ints will also parse as floats. Then you can see if the remainder when divided by 1 is 0 ( if it is, then you have an integer). Then you have a boolean array telling you where the integers are. like so:
import numpy as np
array = np.array(['454.13', '1.243', '8'])
floats = array.astype(float)
remainders = np.remainder(floats, 1)
int_indices = remainders == 0
ints = floats[int_indices]
I deliberately have done it here in 'too many' steps to make it clearer what I mean, hope this helps.
The output is:
>>>ints
array([8.00000000e+00])
>>>int_indices
array([False, False, True])

How can I convert a numpy to a binary (size 8 bits)

I am searching for a dynamic way to perform a numpy convert (integer to binary).
I tried to use the 'astype' way but it didn't work out.
I got a 3-dim matrix like that one:
x = np.array([[[1, 2, 44],[1,5,3]],[[7, 88, 12],[1,15,60]]])
I would like to convert each value of x to its binary form (max size of 8 bits)
for example, if x includes 6 it will be converted to '00000110'.
This is a reference for how to convert integer to binary as I need:
Converting integer to binary in python
Is this what you are looking for?
vfunc = np.vectorize(lambda i: '{0:08b}'.format(i))
x_bin = vfunc(x)
Output of print(x_bin):
[[['00000001' '00000010' '00101100']
['00000001' '00000101' '00000011']]
[['00000111' '01011000' '00001100']
['00000001' '00001111' '00111100']]]

How to calculate complex simultaneous equations in python?

I need to obtain three complex numbers from a set of three equations which is part of an error correction procedure for a set of S-parameters.
import numpy as np
G_A1 = -1 + 0j
G_A2 = 0 + 0j
G_A3 = 1 + 0j
G_M1 = -0.5323 - 0.0163j
G_M2 = -11.1951 - 37.7373j
G_M3 = 0.5528 + 0.1621j
a = np.array([[G_A1,G_A2,G_A3], [1,1,1], [(-G_A1*G_M1),(-G_A2*G_M2),(-G_A3,G_M3)]])
b = np.array([G_M1,G_M2,G_M3])
x = np.linalg.solve(a, b)
print(x)
This gives me the error
a = np.array([[G_A1,G_A2,G_A3], [1,1,1], [(-G_A1*G_M1),(-G_A2*G_M2),(-G_A3,G_M3)]])
TypeError: a float is required
I thought I might as well try to convert the complex values to float but then I get this error.
G_M1 = float(-0.5323 - 0.0163j)
TypeError: can't convert complex to float
If complex values cannot be converted to float, what alternative method should I be using here?
You have a typo in the last entry of last row which makes it a tuple
(-G_A3,G_M3)
and leads to a TypeError as an element. If you correct that the problem goes away. You also don't need to put parentheses around the expressions in this case anyways.

Python: unpacking string of integers to complex numbers

Is there a faster way of reading a buffer of integers to an array of complex numbers?
This works good (if buffer is with floats):
import numpy, struct
binary_string = struct.pack('2f', 1,2)
print numpy.frombuffer(binary_string, dtype=numpy.complex64)
# [ 1. + 2.j]
But, if readed buffer is with integers, there is a problem:
import numpy, struct
binary_string = struct.pack('2i', 1,2)
print numpy.frombuffer(binary_string, dtype=numpy.complex64)
# [ 1.40129846e-45 +2.80259693e-45j]
So, I can't find any faster way to convert it except with a slicing:
import numpy, struct
#for int32
binary_string = struct.pack('2i', 1,2)
ints = numpy.frombuffer(binary_string, dtype=numpy.int32)
print ints[::2] + 1j*ints[1::2]
# [ 1. + 2.j]
#for int16
binary_string = struct.pack('2H', 1,2)
ints = numpy.frombuffer(binary_string, dtype=numpy.int16)
print ints[::2] + 1j*ints[1::2]
# [ 1. + 2.j]
Also, is there any of a "complex number with integers" datatype, so a result could look like:
[1 + 2j]
Thanks.
For a string packed with 4-byte ints you could use:
In [35]: np.frombuffer(struct.pack('2i', 1,2), dtype='i4').astype(np.float32).view(np.complex64)
Out[35]: array([ 1.+2.j], dtype=complex64)
For a string packed with 2-byte ints you could use:
In [34]: np.frombuffer(struct.pack('2H', 1,2), dtype='i2').astype(np.float32).view(np.complex64)
Out[34]: array([ 1.+2.j], dtype=complex64)
The idea here is to let np.frombuffer read the string using an integer dtype appropriate for the string. Then use astype to preserve the integer values but change the underlying representation to float32s. Then use view to reinterpret the underlying data as complex64s (so every two float32s get regarded as one complex64).

Formatting floats in a numpy array [duplicate]

This question already has answers here:
Pretty-print a NumPy array without scientific notation and with given precision
(14 answers)
Closed 3 years ago.
If I have a numpy array like this:
[2.15295647e+01, 8.12531501e+00, 3.97113829e+00, 1.00777250e+01]
how can I move the decimal point and format the numbers so I end up with a numpy array like this:
[21.53, 8.13, 3.97, 10.08]
np.around(a, decimals=2) only gives me [2.15300000e+01, 8.13000000e+00, 3.97000000e+00, 1.00800000e+01] Which I don't want and I haven't found another way to do it.
In order to make numpy display float arrays in an arbitrary format, you can define a custom function that takes a float value as its input and returns a formatted string:
In [1]: float_formatter = "{:.2f}".format
The f here means fixed-point format (not 'scientific'), and the .2 means two decimal places (you can read more about string formatting here).
Let's test it out with a float value:
In [2]: float_formatter(1.234567E3)
Out[2]: '1234.57'
To make numpy print all float arrays this way, you can pass the formatter= argument to np.set_printoptions:
In [3]: np.set_printoptions(formatter={'float_kind':float_formatter})
Now numpy will print all float arrays this way:
In [4]: np.random.randn(5) * 10
Out[4]: array([5.25, 3.91, 0.04, -1.53, 6.68]
Note that this only affects numpy arrays, not scalars:
In [5]: np.pi
Out[5]: 3.141592653589793
It also won't affect non-floats, complex floats etc - you will need to define separate formatters for other scalar types.
You should also be aware that this only affects how numpy displays float values - the actual values that will be used in computations will retain their original precision.
For example:
In [6]: a = np.array([1E-9])
In [7]: a
Out[7]: array([0.00])
In [8]: a == 0
Out[8]: array([False], dtype=bool)
numpy prints a as if it were equal to 0, but it is not - it still equals 1E-9.
If you actually want to round the values in your array in a way that affects how they will be used in calculations, you should use np.round, as others have already pointed out.
You can use round function. Here some example
numpy.round([2.15295647e+01, 8.12531501e+00, 3.97113829e+00, 1.00777250e+01],2)
array([ 21.53, 8.13, 3.97, 10.08])
IF you want change just display representation, I would not recommended to alter printing format globally, as it suggested above. I would format my output in place.
>>a=np.array([2.15295647e+01, 8.12531501e+00, 3.97113829e+00, 1.00777250e+01])
>>> print([ "{:0.2f}".format(x) for x in a ])
['21.53', '8.13', '3.97', '10.08']
You're confusing actual precision and display precision. Decimal rounding cannot be represented exactly in binary. You should try:
> np.set_printoptions(precision=2)
> np.array([5.333333])
array([ 5.33])
[ round(x,2) for x in [2.15295647e+01, 8.12531501e+00, 3.97113829e+00, 1.00777250e+01]]

Categories

Resources