I would like to convert a list that I took out from a txt file into a float so I can make some calculous after in Python. I have the following list:
['1,0,1.2', '2,-1.5,1.2', '3,-1.5,0', '4,0,0', '5,1.5,1.2']
And I would like it to look like this:
[1,0,1.2,2,-1.5,1.2,3,-1.5,0,4,0,0,5,1.5,1.2]
All of them being float type.
Thank you in advance
Two loops are needed here, an outer for the array and an inner loop over the spitted strings.
>>> new = [float(v) for inner in a for v in inner.split(",")]
>>> new
[1.0, 0.0, 1.2, 2.0, -1.5, 1.2, 3.0, -1.5, 0.0, 4.0, 0.0, 0.0, 5.0, 1.5, 1.2]
EDIT:
To up it to accept any case, differentiate between int/float for example:
>>> from ast import literal_eval
>>> new = [literal_eval(v) for inner in a for v in inner.split(",")]
>>> new
[1, 0, 1.2, 2, -1.5, 1.2, 3, -1.5, 0, 4, 0, 0, 5, 1.5, 1.2]
You can do with map,
In [1]: l = ['1,0,1.2', '2,-1.5,1.2', '3,-1.5,0', '4,0,0', '5,1.5,1.2']
In [2]: list(map(float, ','.join(l).split(',')))
Out[2]: [1.0, 0.0, 1.2, 2.0, -1.5, 1.2, 3.0, -1.5, 0.0, 4.0, 0.0, 0.0, 5.0, 1.5, 1.2]
Related
I have two-level list with 3 float element in each part of this list, it looks like that:
[[0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [2.53188872, 2.16784954, 9.49026489], [5.0, 0.0, 0.0]....]
I need to insert a number at the beginning of each element of this list) so that it looks like this:
[[1, 0.0, 0.0, 0.0], [2, 0.0, 5.0, 0.0], [3, 2.53188872, 2.16784954, 9.49026489], [4, 5.0, 0.0, 0.0]....]
I tried using a for loop:
for i in range(len(additional_nodes)):
additional_nodes[i].insert(0, i+1) print(additional_nodes)
but i got something like this:
[[31, 28, 25, 0, 0.0, 0.0, 0.0], [16, 12, 10, 4, 1, 0.0, 5.0, 0.0], [53, 50, 47, 44, 41, 38, 35, 32, 29, 26, 23, 20, 17, 14, 11, 8, 5, 2, 2.53188872, 2.16784954, 9.49026489]...]
what's my problem?
Try this, you have an error in your loop:
for i in range(len(additional_nodes)):
additional_nodes[i].insert(0, i+1)
Or if you want , better enumerate:
for i, lst in enumerate(additional_nodes, start=1):
lst.insert(0, i)
Best to use enumerate like this:
mlist = [[0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [2.53188872, 2.16784954, 9.49026489], [5.0, 0.0, 0.0]]
for i, e in enumerate(mlist, 1):
e.insert(0, i)
print(mlist)
Output:
[[1, 0.0, 0.0, 0.0], [2, 0.0, 5.0, 0.0], [3, 2.53188872, 2.16784954, 9.49026489], [4, 5.0, 0.0, 0.0]]
You can try as below by loop over multi lists
Code:
ls = [[0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [2.53188872, 2.16784954, 9.49026489], [5.0, 0.0, 0.0]]
[[idx, *val] for idx,val in enumerate(ls)]
Output:
[[0, 0.0, 0.0, 0.0],
[1, 0.0, 5.0, 0.0],
[2, 2.53188872, 2.16784954, 9.49026489],
[3, 5.0, 0.0, 0.0]]
I am not sure where it went wrong. Coz it works for me fine.
If u are sure that it is not working and in immediate need of a solution, try reverting and appending and then reverting again. Lol
l = [[0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [2.53188872, 2.16784954, 9.49026489], [5.0, 0.0, 0.0]]
for i in range(len(l)):
l[i] = l[i][::-1]
l[i].append(i+1)
l[i] = l[i][::-1]
print(l)
I have a dictionary with:
inds = [0, 3, 7, 3, 3, 5, 1]
vals = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
d = {'inds': inds, 'vals': vals}
print(d) will get me: {'inds': [0, 3, 7, 3, 3, 5, 1], 'vals': [1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
7.0]}
As you can see, inds(keys) are not ordered, there are dupes, and there are missing ones: range is 0 to 7 but there are only 0,1,3,5,7 distinct integers. I want to write a function that takes the dictionary (d) and decompresses this into a full vector like shown below. For any repeated indices (3 in this case), I'd like to sum the corresponding values, and for the missing indices, want 0.0.
# ind: 0 1 2 3* 4 5 6 7
x == [1.0, 7.0, 0.0, 11.0, 0.0, 6.0, 0.0, 3.0]
Trying to write a function that returns me a final list... something like this:
def decompressor (d, n=None):
final_list=[]
for i in final_list:
final_list.append()
return(final_list)
# final_list.index: 0 1 2 3* 4 5 6 7
# final_list = [1.0, 7.0, 0.0, 11.0, 0.0, 6.0, 0.0, 3.0]
Try it,
xyz = [0.0 for x in range(max(inds)+1)]
for i in range(max(inds)):
if xyz[inds[i]] != 0.0:
xyz[inds[i]] += vals[i]
else:
xyz[inds[i]] = vals[i]
Some things are still not clear to me but supposing you are trying to make a list in which the maximum index is the one you can find in your inds list, and you want a list as a result you can do something like this:
inds = [0, 3, 7, 3, 3, 5, 1]
vals = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
#initialize a list of zeroes with lenght max index
res=[float(0)]*(max(inds)+1)
#[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
#Loop indexes and values in pairs
for i, v in zip(inds, vals):
#Add the value to the corresponding index
res[i] += v
print (res)
#[1.0, 7.0, 0.0, 11.0, 0.0, 6.0, 0.0, 3.0]
inds = [0, 3, 7, 3, 3, 5, 1]
vals = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
first you have to initialise the dictionary , ranging from min to max value in the inds list
max_id = max(inds)
min_id = min(inds)
my_dict={}
i = min_id
while i <= max_id:
my_dict[i] = 0.0
i = i+1
for i in range(len(inds)):
my_dict[inds[i]] += vals[i]
my_dict = {0: 1.0, 1: 7.0, 2: 0, 3: 11.0, 4: 0, 5: 6.0, 6: 0, 7: 3.0}
I have a two lists
kuid -> ['LOdRTFfn', 'Lckq4LkU', 'LcsYHodm']
And NN that is a list of tuple where the first element is a list of indexs of kuid and the other element is an array of values
NN -> [([0, 1, 2], [0.0, 1.2, 1.4]), ([1, 0, 2], [0.0, 1.4, 1.4]), ([2, 0, 1], [0.0, 1.1, 1.4])]
I'd like to keep only the indexes where the values are less then 1.3 for example:
[([0, 1], [0.0, 1.2]), ([1], [0.0]), ([2, 0], [0.0, 1.1])]
and then get the correct value of kuid and build a dataframe:
kuid la lametric
0 LOdRTFfn [LOdRTFfn, Lckq4LkU] [0.0, 1.2]
1 Lckq4LkU [Lckq4LkU] [0.0]
2 LcsYHodm [LcsYHodm, LOdRTFfn] [0.0, 1.1]
Is it possible to do this with list of comprehensions (or other fast solution) avoiding looping? The array could be very large....
Thank you
Here's one way
In [1789]: df = pd.DataFrame(dict(kuid=kuid, NN=[np.array(x) for x in NN]))
In [1790]: df['lametric'] = df.NN.apply(lambda x: x[1][x[1] < 1.3])
In [1791]: df['la'] = df.NN.apply(lambda x: [kuid[int(i)] for i in x[0][x[1] < 1.3]])
In [1792]: df
Out[1792]:
NN kuid lametric \
0 [[0.0, 1.0, 2.0], [0.0, 1.2, 1.4]] LOdRTFfn [0.0, 1.2]
1 [[1.0, 0.0, 2.0], [0.0, 1.4, 1.4]] Lckq4LkU [0.0]
2 [[2.0, 0.0, 1.0], [0.0, 1.1, 1.4]] LcsYHodm [0.0, 1.1]
la
0 [LOdRTFfn, Lckq4LkU]
1 [Lckq4LkU]
2 [LcsYHodm, LOdRTFfn]
Following on from this question:
Unexpectedly large array created with numpy.ones when setting names
When I multiply
a = np.ones([len(sectors),len(columns)])
a[0,:] *= [1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8]
It works fine.
When I try
columns = ["Port Wt", "Bench Wt", "Port Retn", "Bench Retn",
"Attrib", "Select", "Inter", "Total"]
a = np.ones((10,), dtype={"names":columns, "formats":["f8"]*len(columns)})
a[0] *= [1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8]
I get the error
TypeError: cannot convert to an int; scalar object is not a number
I would like to use field-names if possible. What am I doing wrong here?
Many thanks.
A element (row) of this a can be modified by assigning it a tuple. We can take advantage of the fact that lists easily convert to and from arrays, to write:
In [162]: a = np.ones((10,), dtype={"names":columns, "formats":["f8"]*len(columns)})
In [163]: x=[1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8]
In [164]: a[0]=tuple(np.array(x)*list(a[0]))
In [165]: a
Out[165]:
array([(1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8),
...], dtype=[('Port Wt', '<f8'), ('Bench Wt', '<f8'),...
More generally you could write
a[i] = tuple(foo(list(a[i]))
Multiple values ('rows') of a can be set with a list of tuples.
An earlier SO structure array question (https://stackoverflow.com/a/26183332/901925) suggests another solution - create a partner 2d array that shares the same data buffer.
In [311]: a1 = np.empty((10,8)) # conventional 2d array
In [312]: a1.data = a.data # share the a's data buffer
In [313]: a1[0] *= x # do math on a1
In [314]: a1
Out[314]:
array([[ 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8],
...
[ 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ]])
In [315]: a
Out[315]:
array([(1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8),
...
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)],
dtype=[('Port Wt', '<f8'), ('Bench Wt', '<f8'), ('Port Retn', '<f8'), ('Bench Retn', '<f8'), ('Attrib', '<f8'), ('Select', '<f8'), ('Inter', '<f8'), ('Total', '<f8')])
By sharing the data buffer, changes made to a1 affect a as well.
It might be better to view 2d a1 as the primary array, and a as a structured view. a could be constructed on the fly, as needed to display the data, access columns by name, or write to a csv file.
The rows of your array a are not numpy's arrays, the closest things to them are possibly tuples
>>> import numpy as np
>>> columns = ["Port Wt", "Bench Wt", "Port Retn", "Bench Retn",
... "Attrib", "Select", "Inter", "Total"]
>>> a = np.ones((10,), dtype={"names":columns, "formats":["f8"]*len(columns)})
>>> type(a[0,0])
IndexError: too many indices
>>> type(a[0][0])
numpy.float64
>>> type(a[0])
numpy.void
>>>
on the contrary the columns of a are ndarray's and you can multiply them by a list of floats of the correct length (not the nuber of columns but the number of rows)
>>> type(a['Select'])
numpy.ndarray
>>> a['Select']*[1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-27-fc8dc4596098> in <module>()
----> 1 a['Select']*[1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8]
ValueError: operands could not be broadcast together with shapes (10,) (8,)
>>> a['Select']*[1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8, 0,0]
array([ 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 0. , 0. ])
>>>
Edit
In response to a comment from OP: «is it not possible to apply a function to a row in a named array of fields (or tuple) in numpy?»
The only way that I know of is
>>> a[0] = tuple(b*a[c][0] for b, c in zip([1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8],columns))
>>> print a
[(1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)]
>>>
but I'm not the most skilled numpy expert around... maybe one of the least skilled indeed
As seen here How do I convert a Python list into a C array by using ctypes? this code will take a python array and transform it to a C array.
import ctypes
arr = (ctypes.c_int * len(pyarr))(*pyarr)
Which would the way of doing the same with a list of lists or a lists of lists of lists?
For example, for the following variable
list3d = [[[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]]]
I have tried the following with no luck:
([[ctypes.c_double * 4] *2]*3)(*list3d)
# *** TypeError: 'list' object is not callable
(ctypes.c_double * 4 *2 *3)(*list3d)
# *** TypeError: expected c_double_Array_4_Array_2 instance, got list
Thank you!
EDIT: Just to clarify, I am trying to get one object that contains the whole multidimensional array, not a list of objects. This object's reference will be an input to a C DLL that expects a 3D array.
It works with tuples if you don't mind doing a bit of conversion first:
from ctypes import *
list3d = [
[[0.0, 1.0, 2.0, 3.0], [4.0, 5.0, 6.0, 7.0]],
[[0.2, 1.2, 2.2, 3.2], [4.2, 5.2, 6.2, 7.2]],
[[0.4, 1.4, 2.4, 3.4], [4.4, 5.4, 6.4, 7.4]],
]
arr = (c_double * 4 * 2 * 3)(*(tuple(tuple(j) for j in i) for i in list3d))
Check that it's initialized correctly in row-major order:
>>> (c_double * 24).from_buffer(arr)[:]
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0,
0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2,
0.4, 1.4, 2.4, 3.4, 4.4, 5.4, 6.4, 7.4]
Or you can create an empty array and initialize it using a loop. enumerate over the rows and columns of the list and assign the data to a slice:
arr = (c_double * 4 * 2 * 3)()
for i, row in enumerate(list3d):
for j, col in enumerate(row):
arr[i][j][:] = col
I made the change accordingly
a = [[[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]], [[40.0, 1.2, 6.0, 0.3], [50.0, 4.2, 0, 0]]]
arr = (((ctypes.c_float * len(a[0][0])) * len(a[0])) * len(a))
arr_instance=arr()
for i in range(0,len(a)):
for j in range(0,len(a[0])):
for k in range(0,len(a[0][0])):
arr_instance[i][j][k]=a[i][j][k]
The arr_instance is what you want.