I have multiple lists New, J,Pe_new. I want to replace the locations of New mentioned in J with corresponding values in Pe_new. For instance, for J[0]=1, I want to replace New[1] with Pe[0]=10. But getting an error. I present the expected output.
import numpy as np
New=[1.5, 2.9, 2.7, 6.3, 5.5]
J=[1, 2, 4]
Pe_new=[10, 20, 30]
for i in range(0,len(J)):
New=New[J[i]]
print(New)
The error is
in <module>
New=New[J[i]]
TypeError: 'float' object is not subscriptable
The expected output is
[1.5, 10, 20, 6.3, 30]
You can zip the indices and the new values to iterate through them together and assign to New with the value and at the index in each iteration:
for index, value in zip(J, Pe_new):
New[index] = value
One way to do it is to use zip for iterating on both list simultaneously and performing your substituition.
for index,new_item in zip(J,Pe_new):
New[index]=new_item
The error makes complete sense as in the for loop you are trying to access an element of the New list by indexing it with a value from J i.e. New[J[i]], which is not a valid operation since New is a list of floats and you cannot index a float.
You should do the following:
import numpy as np
New=[1.5, 2.9, 2.7, 6.3, 5.5]
J=[1, 2, 4]
Pe_new=[10, 20, 30]
for i in range(0,len(J)):
New[J[i]]=Pe_new[i]
print(New)
Related
I have a list of list defined as 'list' containing two columns that I need to find the average by iterating over the rows. I would normally just use tuble, then sum the column and divide it with the length.
As I need to iterate I am pretty lost of what my approach is going to be? Can anyone point me in a direction
Could you see if this is what is expected:
>> data = [[1,2,3,1, 3], [4,5,6, 2, 1]]
>> print([sum(x)/len(x) for x in data])
>> [2.0, 3.6]
I am using Python3 here.
Also, you may avoid using keywords as variable names. Eg: list
def maxvalues():
for n in range(1,15):
dummy=[]
for k in range(len(MotionsAndMoorings)):
dummy.append(MotionsAndMoorings[k][n])
max(dummy)
L = [x + [max(dummy)]] ## to be corrected (adding columns with value max(dummy))
## suggest code to add new row to L and for next function call, it should save values here.
i have an array of size (k x n) and i need to pick the max values of the first column in that array. Please suggest if there is a simpler way other than what i tried? and my main aim is to append it to L in columns rather than rows. If i just append, it is adding values at the end. I would like to this to be done in columns for row 0 in L, because i'll call this function again and add a new row to L and do the same. Please suggest.
General suggestions for your code
First of all it's not very handy to access globals in a function. It works but it's not considered good style. So instead of using:
def maxvalues():
do_something_with(MotionsAndMoorings)
you should do it with an argument:
def maxvalues(array):
do_something_with(array)
MotionsAndMoorings = something
maxvalues(MotionsAndMoorings) # pass it to the function.
The next strange this is you seem to exlude the first row of your array:
for n in range(1,15):
I think that's unintended. The first element of a list has the index 0 and not 1. So I guess you wanted to write:
for n in range(0,15):
or even better for arbitary lengths:
for n in range(len(array[0])): # I chose the first row length here not the number of columns
Alternatives to your iterations
But this would not be very intuitive because the max function already implements some very nice keyword (the key) so you don't need to iterate over the whole array:
import operator
column = 2
max(array, key=operator.itemgetter(column))[column]
this will return the row where the i-th element is maximal (you just define your wanted column as this element). But the maximum will return the whole row so you need to extract just the i-th element.
So to get a list of all your maximums for each column you could do:
[max(array, key=operator.itemgetter(column))[column] for column in range(len(array[0]))]
For your L I'm not sure what this is but for that you should probably also pass it as argument to the function:
def maxvalues(array, L): # another argument here
but since I don't know what x and L are supposed to be I'll not go further into that. But it looks like you want to make the columns of MotionsAndMoorings to rows and the rows to columns. If so you can just do it with:
dummy = [[MotionsAndMoorings[j][i] for j in range(len(MotionsAndMoorings))] for i in range(len(MotionsAndMoorings[0]))]
that's a list comprehension that converts a list like:
[[1, 2, 3], [4, 5, 6], [0, 2, 10], [0, 2, 10]]
to an "inverted" column/row list:
[[1, 4, 0, 0], [2, 5, 2, 2], [3, 6, 10, 10]]
Alternative packages
But like roadrunner66 already said sometimes it's easiest to use a library like numpy or pandas that already has very advanced and fast functions that do exactly what you want and are very easy to use.
For example you convert a python list to a numpy array simple by:
import numpy as np
Motions_numpy = np.array(MotionsAndMoorings)
you get the maximum of the columns by using:
maximums_columns = np.max(Motions_numpy, axis=0)
you don't even need to convert it to a np.array to use np.max or transpose it (make rows to columns and the colums to rows):
transposed = np.transpose(MotionsAndMoorings)
I hope this answer is not to unstructured. Some parts are suggestions to your function and some are alternatives. You should pick the parts that you need and if you have any trouble with it, just leave a comment or ask another question. :-)
An example with a random input array, showing that you can take the max in either axis easily with one command.
import numpy as np
aa= np.random.random([4,3])
print aa
print
print np.max(aa,axis=0)
print
print np.max(aa,axis=1)
Output:
[[ 0.51972266 0.35930957 0.60381998]
[ 0.34577217 0.27908173 0.52146593]
[ 0.12101346 0.52268843 0.41704152]
[ 0.24181773 0.40747905 0.14980534]]
[ 0.51972266 0.52268843 0.60381998]
[ 0.60381998 0.52146593 0.52268843 0.40747905]
numpy.partition() also does sorting the internal of elements of the array.
I have been trying to do simple sorting based on first element of all the elements of array.
import numpy as np
a = np.array([[5.2, 4.3], [200.2, 6.2], [1.4, 112.2]])
np.partition(a, (1,a.shape[1]-1), axis = 1)
Output:
array([[ 4.3, 5.2],
[ 6.2, 200.2],
[ 1.4, 112.2]])
I don't understand the working of np.partition() here. Any resources for detail on numpy.partition()?
Specifically, I want to modify the arguments of the method to generate the following output:
array([[ 1.4, 112.2],
[ 5.2, 4.3],
[ 200.2, 6.2]])
np.partition() ensures that values at particular indices are the same as they would be if the array were to be fully sorted (e.g. with np.sort). (The order of the values at the other indices is not guaranteed to be anything meaningful.)
The axis=1 argument means that this operation will be applied individually to each row.
Here, the indices you've passed are (1, a.shape[1]-1) which is equivalent to (1, 1) in this case. Repeating an index has no special meaning, so on each row, the value in the second column (index 1) will be the same as if each row was in sorted order.
Now, when the operation is applied, you see in the returned array that the higher values in the first and second rows have been moved to this second column. The third row was already in its sorted order and so is unchanged.
This is really all there is to the function: the NumPy documentation covers a few further details. If you're feeling particularly brave, you can find the source code implementing the introselect algorithm used by np.partition() in all its glory here.
If I understand correctly, you just want to sort the rows in your array according to the values in the first column. You can do this using np.argsort:
# get an array of indices that will sort the first column in ascending order
order = np.argsort(a[:, 0])
# index into the row dimension of a
a_sorted = a[order]
print(a_sorted)
# [[ 1.4 112.2]
# [ 5.2 4.3]
# [ 200.2 6.2]]
If you want a partial sort rather than a full sort, you could use np.argpartition in much the same way:
# a slightly larger example array in order to better illustrate what
# argpartition does
b = np.array([[ 5.2, 4.3],
[200.2, 6.2],
[ 3.6, 85.1],
[ 1.4, 112.2],
[ 12.8, 60.0],
[ 7.6, 23.4]])
# get a set of indices to reorder the rows of `b` such that b[2, 0] is in its
# final 'sorted' position, and all elements smaller or larger than it will be
# placed before and after it respectively
partial_order = np.argpartition(b[:, 0], 2)
# the first (2+1) elements in the first column are guaranteed to be smaller than
# the rest, but apart from that the order is arbitrary
print(b[partial_order])
# [[ 1.4 112.2]
# [ 3.6 85.1]
# [ 5.2 4.3]
# [ 200.2 6.2]
# [ 12.8 60. ]
# [ 7.6 23.4]]
I'd like to filter a NumPy 2-d array by checking whether another array contains a column value. How can I do that?
import numpy as np
ar = np.array([[1,2],[3,-5],[6,-15],[10,7]])
another_ar = np.array([1,6])
new_ar = ar[ar[:,0] in another_ar]
print new_ar
I hope to get [[1,2],[6,-15]] but above code prints just [1,2].
You can use np.where,but note that as ar[:,0] is a list of first elements if ar you need to loop over it and check for membership :
>>> ar[np.where([i in another_ar for i in ar[:,0]])]
array([[ 1, 2],
[ 6, -15]])
Instead of using in, you can use np.in1d to check which values in the first column of ar are also in another_ar and then use the boolean index returned to fetch the rows of ar:
>>> ar[np.in1d(ar[:,0], another_ar)]
array([[ 1, 2],
[ 6, -15]])
This is likely to be much faster than using any kind of for loop and testing membership with in.
I'm using Python 2.7.5 and this format is not working. As far as I remember it works on my other computer which also has 2.7
train_data.ix[:,1:-1]
The error I get is:
AttributeError: 'list' object has no attribute 'ix'
If I use train_data[:,1:-1] then the error is:
TypeError: list indices must be integers, not tuple
How can I solve this?
Thanks!
Lists and NumPy arrays do not have an ix method:
In [8]: import numpy as np
In [10]: x = np.array([])
In [11]: x.ix
AttributeError: 'numpy.ndarray' object has no attribute 'ix'
But Pandas Series and DataFrames do have an ix method:
In [16]: import pandas as pd
In [17]: y = pd.Series([1,2])
In [18]: y.ix[0]
Out[18]: 1
In [19]: y.ix[1]
Out[19]: 2
If train_data is a Pandas DataFrame, then train_data.ix[:,1:-1]
selects all rows from the second to next-to-last columns. The : indicates all rows, the 1:-1 indicates the second to next-to-last columns.
The syntax for python slice notation is list:
list[start:end:step]
If there are any commas in the slice notation it will give you the tuple error.
if you use
list1=[1,2,3,4,5,6,7]
>>> list1[:1:-1]
[7, 6, 5, 4, 3]
and if you want to reverse the list, you can use,
>>> list1[::-1]
[7, 6, 5, 4, 3, 2, 1]
The first error says that list object doesn't have attribute ix (and it doesn't have, in fact):
>>> [].ix
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'ix'
In the second piece of code you are trying to use comma in the slice. According to this document you can't do it with python's lists. AFAIK you can do it with some numpy structures, so you need to convert your list to one of them.
The direct answer to your question is that it is not working because your train_data is a list. It appears that the train_data in the code you are trying to understand was a Pandas DataFrame object due to the .ix property you are using.