get values from a dictionary using a list of indexes - python

Given a list:
x = [0.0, 0.87, 0.0, 0.0, 0.0, 0.32, 0.46, 0.0, 0.0, 0.10, 0.0, 0.0]
I want to get the indexes of all the values that are not 0 and store them in d['inds']
Then using the indexes in d['inds'] go through the list of x and get the values.
So I would get something like:
d['inds'] = [1, 5, 6, 9]
d['vals'] = [0.87, 0.32, 0.46, 0.10]
I already got the indexes using:
d['inds'] = [i for i,m in enumerate(x) if m != 0]
but I'm not sure how to get d['vals']

d['vals'] = [x[i] for i in d['inds']]
Better yet, do both at once:
vals = []
inds = []
for i,v in enumerate(x):
if v!=0:
vals.append(v)
inds.append(i)
d['vals']=vals
d['inds']=inds
or
import numpy as np
d['inds'],d['vals'] = np.array([(i,v) for i,v in enumerate(x) if v!=0]).T

you can use numpy, its indexing features are designed for tasks like this one:
import numpy as np
x = np.array([0.0, 0.87, 0.0, 0.0, 0.0, 0.32, 0.46, 0.0, 0.0, 0.10, 0.0, 0.0])
x[x!=0]
Out: array([ 0.87, 0.32, 0.46, 0.1 ])
and if you're still interested in the indices:
np.argwhere(x!=0)
Out:
array([[1],
[5],
[6],
[9]], dtype=int64)

You can use a dict comprehension:
m = {i:j for i,j in enumerate(x) if j!=0}
list(m.keys())
Out[183]: [1, 5, 6, 9]
list(m.values())
Out[184]: [0.87, 0.32, 0.46, 0.1]
if you want to save this in a dictionary d then you can do:
d = {}
d['vals']=list(m.values())
d['ind']=list(m.keys())
d
{'vals': [0.87, 0.32, 0.46, 0.1], 'ind': [1, 5, 6, 9]}

Using Pandas:
x = [0.0, 0.87, 0.0, 0.0, 0.0, 0.32, 0.46, 0.0, 0.0, 0.10, 0.0, 0.0]
import pandas as pd
data = pd.DataFrame(x)
inds = data[data[0]!=0.0].index
print(inds)
Output: Int64Index([1, 5, 6, 9], dtype='int64')

Much easier:
df['vals']=list(filter(None,x))
df['idx']=df['vals'].apply(x.index)
Exaplantion:
Use filter(None,x) for filtering non-0 values, (None basically neans no statement (or not False)
Then use pandas apply for getting the index basically go trough the 'vals' column then then get the values index in the list x

Related

Printing between two number ranges with a given step value

I am new to loops, and I am trying to iterate over all items in a list, and I need to generate the values between 0 and 2 with a given step value. I have tried to use the "range" function, but cannot get it to work.
The end result should look something like this (doesn't have to be in a pandas dataframe, just for illustrative purposes):
import pandas as pd
import numpy as np
data = {'range_0.5' : [0,0.5,1,1.5,2, np.nan, np.nan, np.nan, np.nan],
'range_0.25' : [0,0.25,0.5,0.75,1,1.25,1.5,1.75,2]}
df = pd.DataFrame(data)
df
Here is what I have tried:
import numpy
x = []
seq = [0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.00390625]
for i in seq:
x = range(0, 2, i)
The following error is thrown:
TypeError Traceback (most recent call last)
Input In [10], in <cell line: 1>()
1 for i in seq:
----> 2 x = range(0, 2, i)
TypeError: 'float' object cannot be interpreted as an integer
How can I properly create my loop?
np.arange()
You can use numpy.arange() which supports floats as step values.
import numpy as np
for step in [0.5, 0.25]:
print([i for i in np.arange(0, 2, step))
Expected output:
[0.0, 0.5, 1.0, 1.5]
[0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75]
To include 2 just add the step value once again:
for step in [0.5, 0.25]:
print([i for i in np.arange(0, 2 + step, step)])
Expected output:
[0.0, 0.5, 1.0, 1.5, 2.0]
[0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
np.linspace()
Alternatively you can use np.linspace():
This has the ability to include the endpoint using endpoint=True;
for step in [0.5, 0.25]:
print([i for i in np.linspace(0, 2, int(2 // step) + 1, endpoint=True)])
Expected output:
[0.0, 0.5, 1.0, 1.5, 2.0]
[0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]

How to delete certain number from a list in list using the index in python?

I have a list in a list, and I am trying to delete the third number of each sublist, but every time I am getting an error TypeError: list indices must be integers or slices, not list
a = [[0.0, 0.0, 0.0], [0.19, 0.36, 0.0], [0.24, 0.42, 0.0], [0.16, 0.08, 0.0], [0.05, -0.57, 0.0] ]
Desired result:-
a_updated = [[0.0, 0.0], [0.19, 0.36], [0.24, 0.42], [0.16, 0.08], [0.05, -0.57] ]
In the second part of my code, I wanted to merge this sublist according to a dictionary shown below, for example, the first value of dictionary:- 1: [1, 2] shows the merging of 1st and 2nd values i.e. [0, 0, 0.19, 0.36].
I guess this part of my code is right!
dict_a = { {1: [1, 2], 2: [2, 4], 3: [3, 5], 4: [4, 5] }
my attempt:-
dict_a = { 1: [1, 2], 2: [2, 4], 3: [3, 5], 4: [4, 5]}
a = [[0.0, 0.0], [0.19, 0.36], [0.24, 0.42], [0.16, 0.08], [0.05, -0.57]]
# first part
for i in a:
for j in a[i]:
del j[2]
print(j)
#second part
a_list = []
list_of_index = []
for i in dict_a:
index= []
a_list.append(index)
for j in dict_a_updated[i]:
print(j-1)
index.extend(a_updated[j-1])
print('index',index)
Error output -
file "D:\python programming\random python files\4 may axial dis.py", line 18, in <module>
for j in X[i]:
TypeError: list indices must be integers or slices, not list
You can slice the sublists in a list comprehension to build a_updated:
a_updated = [s_lst[:2] for s_lst in a]
Output:
[[0.0, 0.0], [0.19, 0.36], [0.24, 0.42], [0.16, 0.08], [0.05, -0.57]]
To build dict_a_updated, you can use a loop. Note that list indices start from 0 in Python but your index starts from 1, so we have to subtract 1 here:
dict_a_updated = {}
for k, v in dict_a.items():
tmp = []
for i in v:
tmp.extend(a_updated[i-1])
dict_a_updated[k] = tmp
Output:
{1: [0.0, 0.0, 0.19, 0.36],
2: [0.19, 0.36, 0.16, 0.08],
3: [0.24, 0.42, 0.05, -0.57],
4: [0.16, 0.08, 0.05, -0.57]}
Given a list of lists:
a = [[0.0, 0.0, 0.0], [0.19, 0.36, 0.0], [0.24, 0.42, 0.0], [0.16, 0.08, 0.0], [0.05, -0.57, 0.0]]
The first solution: if the third element is the last element in all arrays.
firstSolution = [el[:-1] for el in a]
print(firstSolution)
The second solution: is to remove the element by its index.
for el in a:
el.pop(2)
print(a)
You can achieve you goal with a single dictionary comprehension and itertools.chain, without needing to first rework a:
from itertools import chain
out = {k: list(chain.from_iterable(a[i-1][:2] for i in v))
for k,v in dict_a.items()}
Output:
{1: [0.0, 0.0, 0.19, 0.36],
2: [0.19, 0.36, 0.16, 0.08],
3: [0.24, 0.42, 0.05, -0.57],
4: [0.16, 0.08, 0.05, -0.57]}
a = [[0.0, 0.0, 0.0], [0.19, 0.36, 0.0], [0.24, 0.42, 0.0], [0.16, 0.08, 0.0], [0.05, -0.57, 0.0] ]
dict_a = {1: [1, 2], 2: [2, 4], 3: [3, 5], 4: [4, 5] }
# first part
for i in range(0,len(a)): # for every sublist position
a[i] = a[i][0:2]
dict_lists = {}
for key,value in dict_a.items():
dict_lists[key] = [a[value[0]-1], a[value[1]-1]]
Output:
In[19]: dict_lists
Out[19]:
{1: [[0.0, 0.0], [0.19, 0.36]],
2: [[0.19, 0.36], [0.16, 0.08]],
3: [[0.24, 0.42], [0.05, -0.57]],
4: [[0.16, 0.08], [0.05, -0.57]]}

How to get the original indexes after sorting a list in python

I have a list as follows.
mylist= [0.0, 0.4, 0.81, 1.0, 0.9, 20.7, 0.0, 0.8, 1.0, 20.7]
I want to get the indexes of the top 4 elements of the list (i.e [5, 9, 3, 8]) and remove the indexes that have a value lesser than or equal to 1 (<=1).
Therefore my final output should be [5, 9]
My current code is as follows:
sorted_mylist = sorted(mylist, reverse = True)[:4]
for ele in sorted_mylist:
if ele>1:
print(mylist.index(ele))
However, it returns [5, 5], which is incorrect.
Please let me know how I can fix this in python?
You should use enumerate
mylist= [0.0, 0.4, 0.81, 1.0, 0.9, 20.7, 0.0, 0.8, 1.0, 20.7]
indices = [index for index, value in sorted(enumerate(mylist), reverse=True, key=lambda x: x[1]) if value > 1][:4]
# [5, 9]
You can sort the list along with the index, so that the index is easily retrieved later like:
Code:
sorted_mylist = sorted(((v, i) for i, v in enumerate(mylist)), reverse=True)
Test Code:
mylist = [0.0, 0.4, 0.81, 1.0, 0.9, 20.7, 0.0, 0.8, 1.0, 20.7]
sorted_mylist = sorted(((v, i) for i, v in enumerate(mylist)), reverse=True)
result = []
for i, (value, index) in enumerate(sorted_mylist):
if i == 4:
break
if value > 1:
result.append(index)
print(result)
Results:
[9, 5]
All above answers are good, but if you do not persist to use your current code, and just want to solve your problem itself, here is another option with pandas, just FYI:
import pandas as pd
mylist= [0.0, 0.4, 0.81, 1.0, 0.9, 20.7, 0.0, 0.8, 1.0, 20.7]
s = pd.Series(mylist).sort_values(ascending=False)[:4]
s = s[s > 1]
print s.index.tolist()

Build a dataframe from a filtered list of tuple

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]

Use python to split a list of values into two lists when negative value occurs when looping

Let's say I have a list of floats. I was wondering how I would loop through the list and whenever a negative value occurs, to split the list into two separate lists.
The initial set of values:
[0.1,
0.5,
3.2,
8.2,
0.0,
19.7,
0.0,
-0.8,
-12.0,
-8.2,
-2.5,
-6.9,
-1.3,
0.0]
Example result I am looking for:
listA = [0.1, 0.5, 3.2, 8.2, 0.0, 19.7, 0.0]
listB = [-0.8, -12.0, -8.2, -2.5, -6.9, -1.3, 0.0]
The key here would be that the length of the list would vary, and the position at which the first negative value occurs is never the same.
So in short: wherever the first negative value occurs, split into two separate lists.
Any ideas? Any help would be greatly appreciated.
-Cheers
First, you may use generator expression to find the index of the first negative value:
neg = next((i for i, v in enumerate(values) if v < 0), -1)
Then, slice your list (assuming neg != -1):
listA, listB = values[:neg], values[neg:]
The idea is very simple, looping through your list, if the number is positive then add it to the first list, if the number is negative then turn the saw_negative = True and from now on append to the second list.
li = [0.1, 0.5, 3.2, 8.2, 0.0, 19.7, 0.0, -0.8, -12.0, -8.2, -2.5, -6.9, -1.3, 0.0]
first_li = []
second_li = []
saw_negative = False
for item in li:
if item >= 0 and not saw_negative:
first_li.append(item)
elif item < 0 or saw_negative:
saw_negative = True
second_li.append(item)
print first_li
print second_li
Output:
[0.1, 0.5, 3.2, 8.2, 0.0, 19.7, 0.0]
[-0.8, -12.0, -8.2, -2.5, -6.9, -1.3, 0.0]
This is another approach, until the number is negative append the number to the first list, whenever the number is negative append the rest of the list to the second list and break the loop
li = [0.1, 0.5, 3.2, 8.2, 0.0, 19.7, 0.0, -0.8, -12.0, -8.2, -2.5, -6.9,
-1.3, 0.0]
first_li = []
second_li = []
for index, item in enumerate(li):
if item < 0:
second_li = li[index:]
break
first_li.append(item)
print first_li
print second_li
Output:
[0.1, 0.5, 3.2, 8.2, 0.0, 19.7, 0.0]
[-0.8, -12.0, -8.2, -2.5, -6.9, -1.3, 0.0]
This can also be done in functional style using the groupby and chain functions from the itertools standard library module:
from itertools import groupby, chain
def split_at_first_negative(lst):
"""Split the list at the first occurrence of a negative value.
>>> split_at_first_negative([1, 2, 3, -1, -5, -3, 5, -6, 1])
([1, 2, 3], [-1, -5, -3, 5, -6, 1])
"""
groups = groupby(lst, lambda x: x >= 0)
first = list(next(groups)[1])
second = list(chain.from_iterable(g[1] for g in groups))
return first, second

Categories

Resources