I have a list:
l = [['a', 10, 30], ['b', 34, 89], ['c', 40, 60],['d',30,20]]
where the first item inside each sublist is the name and other two number are marks (sub1 and sub2)
The nested lists can be dynamic, i.e the number of nested lists can change according to function.
What I am looking for is to find
average of subj 1 i.e (10+34+40+30)/4 and
similarly sub2 (30+89+60+20)/4
also average marks of a: (10+30)/2
average marks of b: (34+89)/2 and so on.
I tried:
c = 0
for i in range(0,len(list_marks1)):
c += list_marks1[i][1]
sub_1avg = float(c)/len(list_marks1)
d = 0
for i in range(0,len(list_marks1)):
d += list_marks1[i][2]
sub_2avg = float(d)/len(list_marks1)
but this is not correct.
Is there any optimal way to do this? Since the number of subjects in my nested lists can also change.
You could just use sum and a generator expression:
>>> l= [['a', 10, 30], ['b', 34, 89], ['c', 40, 60],['d',30,20]]
>>> length = float(len(l)) # in Python 3 you don't need the "float"
>>> sum(subl[1] for subl in l) / length
28.5
>>> sum(subl[2] for subl in l) / length
49.75
Or even do that inside a list comprehension:
>>> [sum(subl[subj] for subl in l) / length for subj in range(1, 3)]
[28.5, 49.75]
Similarly for the average of one sublist:
>>> length = float(len(l[0])) - 1
>>> [sum(subl[1:]) / length for subl in l]
[20.0, 61.5, 50.0, 25.0]
When you have python 3.4 or newer you can replace the sum / length with statistics.mean:
>>> from statistics import mean
>>> [mean(subl[subj] for subl in l) for subj in range(1, 3)]
[28.5, 49.75]
>>> [mean(subl[1:]) for subl in l]
[20, 61.5, 50, 25]
You asked about the best way so I probably should mention that there are packages dedicated for tabular data. For example If you have pandas it's even easier using DataFrame and mean:
>>> import pandas as pd
>>> df = pd.DataFrame(l, columns=['name', 'x', 'y'])
>>> df[['x', 'y']].mean(axis=0)
x 28.50
y 49.75
dtype: float64
>>> df[['x', 'y']].mean(axis=1)
0 20.0
1 61.5
2 50.0
3 25.0
dtype: float64
A fucnitonal approach:
l= [['a', 10, 30], ['b', 34, 89], ['c', 40, 60],['d',30,20]]
map(lambda x: sum(x)/float(len(x)), zip(*l)[1:])
[28.5, 49.75]
This way will work for any sublist length
l= [['a', 10, 30], ['b', 34, 89], ['c', 40, 60],['d',30,20]]
sub1_avg = sum(n for _,n, _ in l)/float(len(l))
sub2_avg = sum(n for _,_, n in l)/float(len(l))
student_avgs = [{x[0]: sum(x[1:])//float((len(x)-1))} for x in l]
print "Sub1 avg - {}\nSub2 avg - {}\nstudent avg - {}".format(sub1_avg, sub2_avg, student_avgs)
sample output
Sub1 avg - 28.5
Sub2 avg - 49.75
student avg - [{'a': 20.0}, {'b': 61.0}, {'c': 50.0}, {'d': 25.0}]
Related
If there are two lists:
One being the items:
items = ['A', 'A', 'A', 'B', 'B', 'C', 'C']
The other being their indexes:
index = [0, 15, 20, 2, 16, 7, 17]
ie. The first 'A' is in index 0, the second 'A' is in index 15, etc.
How would I be able to get the closest indexes for the unique items, A, B, and C
ie. Get 15, 16, 17?
You can achieve this with a simples script. Consider those two lists as input, you just want to find the index on the letter list and it's correspondence on number list:
list_of_repeated=[]
list_of_closest=[]
for letter in list_letter:
if letter in list_of_repeated:
continue
else:
list_of_repeated.append(letter)
list_of_closest.append(list_number[list_letter.index(letter)])
What you are trying to do is minimize the sum of differences between indices.
You can find the minimal combination like this:
import numpy as np
from itertools import product
items = ['A', 'A', 'A', 'B', 'B', 'C', 'C']
index = [0, 15, 20, 2, 16, 7, 17]
cost = np.inf
for combination in product(*[list(filter(lambda x: x[0] == i, zip(items, index))) for i in set(items)]):
diff = sum(abs(np.ediff1d([i[1] for i in combination])))
if diff < cost:
cost = diff
idx = combination
print(idx)
This is bruteforcing the solution, there may be more elegant / faster ways to do this, but this is what comes to my mind on the fly.
i am trying to find 3 lowest number from a list and using those indexes to find corresponding value from another list.
this is an example of what i have tried
a = [12, 83, 22, 30, 57, 32, 88, 46, 20, 26, 78, 65, 45, 56, 74]
b = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o']
lowest = lowest2 = lowest3 = max(a)
indexes = []
for i in range(0,len(a)):
if a[i] < lowest :
lowest = a[i]
print(b[i])
elif a[i] < lowest2 and a[i] > lowest:
lowest2 = a[i]
print(b[i])
elif a[i] < lowest3 and a[i] > lowest2:
lowest3 = a[i]
print(b[i])
print(lowest,lowest2,lowest3)
i can only supposed to use anaconda library and no this is not assignment this is a very small part of a program i have been trying to do.
output: a
b
c
d
i
j
12 20 26
What you can do is sort the list a and return it's index values,
>>> a = [12, 83, 22, 30, 57, 32, 88, 46, 20, 26, 78, 65, 45, 56, 74]
>>> n_min_values = 3
>>> sorted(range(len(a)), key=lambda k: a[k])[:n_min_values]
[0, 8, 2] # index values
and iterate through this index values list to get corresponding values from list b,
>>> b = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o']
>>> for i in sorted(range(len(a)), key=lambda k: a[k])[:n_min_values ]:
print(b[i])
a
i
c
OR
Using list comprehesion,
>>> [b[i] for i in sorted(range(len(a)), key=lambda k: a[k])[:n_min_values ]]
['a', 'i', 'c'] # your output
Heaps are good at doing this sort of thing, especially if the order of the smallest items isn't important.
Here's a small example using heapq.nsmallest on a with its zipped indices.
from heapq import nsmallest
from operator import itemgetter
n = 3
idx, _ = zip(*nsmallest(n, enumerate(a), key=itemgetter(1)))
idx
# (0, 8, 2)
[b[i] for i in idx] # your result
# ['a', 'i', 'c']
I have two equal lists, their values are connected to each other:
list1 = [29, 4, 15, 4, 5, 5]
list2 = [57.49999999999999, 89.74358974358975, 78.94736842105263, 100.0, 94.44444444444444, 57.89473684210527]
How do I change the i-th value in list1 to 40 if the corresponding i-th value in list2 is less than 65.0?
You should use zip as I wrote in a comment, I think that would be the cleanest solution.
new_list1 = []
for a, b in zip(list1, list2):
if b < 65.0:
new_list1.append(40)
else:
new_list1.append(a)
A list comprehension with the ternary operator and zip should do the trick:
[40 if list2_val < 65.0 else list1_val
for list1_val, list2_val in zip(list1, list2)]
Out[2]: [40, 4, 15, 4, 5, 40]
FWIW, this more compact (but perhaps more difficult to read) syntax will produce an identical result to that of Tobias's answer.
Depending on how long your lists are, you might try using pandas and numpy:
>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({'list1': list1, 'list2': list2})
>>> df
list1 list2
0 29 57.500000
1 4 89.743590
2 15 78.947368
3 4 100.000000
4 5 94.444444
5 5 57.894737
>>> df['list1_new'] = np.where(df['list2'] < 65, 40, df['list1'])
list1 list2 list1_new
0 29 57.500000 40
1 4 89.743590 4
2 15 78.947368 15
3 4 100.000000 4
4 5 94.444444 5
5 5 57.894737 40
You have to iterate on list2 to find which index has a value smaller than 65.0. With this index number you can replace nth value in list1:
list1 = [29, 4, 15, 4, 5, 5]
list2 = [57.49999999999999, 89.74358974358975, 78.94736842105263, 100.0,
94.44444444444444, 57.89473684210527]
for i in range(0, len(list1)):
if list2[i] < 65.0:
list1[i] = 40
print(list1)
Is there a way I can subtract two arrays, but making sure I am subtracting elements that have the same day, hour, year, and or minute values?
list1 = [[10, '2013-06-18'],[20, '2013-06-19'], [50, '2013-06-23'], [15, '2013-06-30']]
list2 = [[5, '2013-06-18'], [5, '2013-06-23'] [20, '2013-06-25'], [20, '2013-06-30']]
Looking for:
list1-list2 = [[5, '2013-06-18'], [45, '2013-06-23'] [10, '2013-06-30']]
How about using a defaultdict of lists?
import itertools
from operator import sub
from collections import defaultdict
def subtract_lists(l1, l2):
data = defaultdict(list)
for sublist in itertools.chain(l1, l2):
value, date = sublist
data[date].append(value)
return [(reduce(sub, v), k) for k, v in data.items() if len(v) > 1]
list1 = [[10, '2013-06-18'],[20, '2013-06-19'], [50, '2013-06-23'], [15, '2013-06-30']]
list2 = [[5, '2013-06-18'], [5, '2013-06-23'], [20, '2013-06-25'], [20, '2013-06-30']]
>>> subtract_lists(list1, list2)
[(-5, '2013-06-30'), (45, '2013-06-23'), (5, '2013-06-18')]
>>> # if you want them sorted by date...
>>> sorted(subtract_lists(list1, list2), key=lambda t: t[1])
[(5, '2013-06-18'), (45, '2013-06-23'), (-5, '2013-06-30')]
Note that the difference for date 2013-06-30 is -5, not +5.
This works by using the date as a dictionary key for a list of all values for the given date. Then those lists having more than one value in its list are selected, and the values in those lists are reduced by subtraction. If you want the resulting list sorted, you can do so using sorted() with the date item as the key. You could move that operation into the subtract_lists() function if you always want that behavior.
I think this code does what you want:
list1 = [[10, '2013-06-18'],[20, '2013-06-19'], [50, '2013-06-23'], [15, '2013-06-30']]
list2 = [[5, '2013-06-18'], [5, '2013-06-23'], [20, '2013-06-25'], [20, '2013-06-30']]
list1=dict([[i[1],i[0]] for i in list1])
list2=dict([[i[1],i[0]] for i in list2])
def minus(a,b):
return { k: a.get(k, 0) - b.get(k, 0) for k in set(a) & set(b) }
minus(list2,list1)
# returns the below, which is now a dictionary
{'2013-06-18': 5, '2013-06-23': 45, '2013-06-30': 5}
# you can convert it back into your format like this
data = [[value,key] for key, value in minus(list1,list2).iteritems()]
But you seem to have an error in your output data. If you want to include data when it's in either list, define minus like this instead:
def minus(a,b):
return { k: a.get(k, 0) - b.get(k, 0) for k in set(a) | set(b) }
See this answer, on Merge and sum of two dictionaries, for more info.
If I have two lists (may be with different len):
x = [1,2,3,4]
f = [1,11,22,33,44,3,4]
result = [11,22,33,44]
im doing:
for element in f:
if element in x:
f.remove(element)
I'm getting
result = [11,22,33,44,4]
UPDATE:
Thanks to #Ahito:
In : list(set(x).symmetric_difference(set(f)))
Out: [33, 2, 22, 11, 44]
This article has a neat diagram that explains what the symmetric difference does.
OLD answer:
Using this piece of Python's documentation on sets:
>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # letters in both a and b
{'a', 'c'}
>>> a ^ b # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}
I came up with this piece of code to obtain unique elements from two lists:
(set(x) | set(f)) - (set(x) & set(f))
or slightly modified to return list:
list((set(x) | set(f)) - (set(x) & set(f))) #if you need a list
Here:
| operator returns elements in x, f or both
& operator returns elements in both x and f
- operator subtracts the results of & from | and provides us with the elements that are uniquely presented only in one of the lists
If you want the unique elements from both lists, this should work:
x = [1,2,3,4]
f = [1,11,22,33,44,3,4]
res = list(set(x+f))
print(res)
# res = [1, 2, 3, 4, 33, 11, 44, 22]
Based on the clarification of this question in a new (closed) question:
If you want all items from the second list that do not appear in the first list you can write:
x = [1,2,3,4]
f = [1,11,22,33,44,3,4]
result = set(f) - set(x) # correct elements, but not yet in sorted order
print(sorted(result)) # sort and print
# Output: [11, 22, 33, 44]
x = [1, 2, 3, 4]
f = [1, 11, 22, 33, 44, 3, 4]
list(set(x) ^ set(f))
[33, 2, 22, 11, 44]
if you want to get only unique elements from the two list then you can get it by..
a=[1,2,3,4,5]
b= [2,4,1]
list(set(a) - set(b))
OP:- [3, 5]
Input :
x = [1,2,3,4]
f = [1,11,22,33,44,3,4]
Code:
l = list(set(x).symmetric_difference(set(f)))
print(l)
Output :
[2, 22, 33, 11, 44]
Your method won't get the unique element "2". What about:
list(set(x).intersection(f))
Simplified Version & in support of #iopheam's answer.
Use Set Subtraction.
# original list values
x = [1,2,3,4]
f = [1,11,22,33,44,3,4]
# updated to set's
y = set(x) # {1, 2, 3, 4}
z = set(f) # {1, 33, 3, 4, 11, 44, 22}
# parsed to the result variable
result = z - y # {33, 11, 44, 22}
# printed using the sorted() function to display as requested/stated by the op.
print(f"Result of f - x: {sorted(result)}")
# Result of f - x: [11, 22, 33, 44]
v_child_value = [{'a':1}, {'b':2}, {'v':22}, {'bb':23}]
shop_by_cat_sub_cats = [{'a':1}, {'b':2}, {'bbb':222}, {'bb':23}]
unique_sub_cats = []
for ind in shop_by_cat_sub_cats:
if ind not in v_child_value:
unique_sub_cats.append(ind)
unique_sub_cats = [{'bbb': 222}]
Python code to create a unique list from two lists :
a=[1,1,2,3,5,1,8,13,6,21,34,55,89,1,2,3]
b=[1,2,3,4,5,6,7,8,9,10,11,12,2,3,4]
m=list(dict.fromkeys([a[i] for i in range(0,len(a)) if a [i] in a and a[i] in b and a[i]]))
print(m)
L=[]
For i in x:
If i not in f:
L. Append(I)
For i in f:
If I not in x:
L. Append(I)
Return L