Aggregation in array element - python - python

I have a OP : {'2017-05-06': [3, 7, 8],'2017-05-07': [3, 9, 10],'2017-05-08': [4]}
from the OP I just want another OP :
{'2017-05-06': [15, 11, 10],'2017-05-07': [19, 13, 12],'2017-05-08': [4]}
which means:
Ncleand is 2017-05-06
element total is 18 so '2017-05-06': [3 -18, 7-18, 8-18] = '2017-05-06': [15, 11, 10]
likewise all elements data.
So final output is {'2017-05-06': [15, 11, 10],'2017-05-07': [19, 13, 12],'2017-05-08': [4]}
How to do this?
Note : I am using python 3.6.2 and pandas 0.22.0
code so far :
import pandas as pd
dfs = pd.read_excel('ff2.xlsx', sheet_name=None)
dfs1 = {i:x.groupby(pd.to_datetime(x['date']).dt.strftime('%Y-%m-%d'))['duration'].sum() for i, x in dfs.items()}
d = pd.concat(dfs1).groupby(level=1).apply(list).to_dict()
actuald = pd.concat(dfs1).div(80).astype(int)
sum1 = actuald.groupby(level=1).transform('sum')
m = actuald.groupby(level=1).transform('size') > 1
cleand = sum1.sub(actuald).where(m, actuald).groupby(level=1).apply(list).to_dict()
print (cleand)
From the cleand I want to do this?

In a compact (but somehow inefficient) way:
>>> op = {'2017-05-06': [3, 7, 8],'2017-05-07': [3, 9, 10],'2017-05-08': [4]}
>>> { x:[sum(y)-i for i in y] if len(y)>1 else y for x,y in op.items() }
#output:
{'2017-05-06': [15, 11, 10], '2017-05-07': [19, 13, 12], '2017-05-08': [4]}

def get_list_manipulation(list_):
subtraction = list_
if len(list_) != 1:
total = sum(list_)
subtraction = [total-val for val in list_]
return subtraction
for key, values in data.items():
data[key] = get_list_manipulation(values)
>>>{'2017-05-06': [15, 11, 10], '2017-05-07': [19, 13, 12], '2017-05-08': [4]}

Related

Get dictionary from a dataframe

I have a dataframe like below:
df = pd.DataFrame({
'Aapl': [12, 5, 8],
'Fs': [18, 12, 8],
'Bmw': [6, 18, 12],
'Year': ['2020', '2025', '2030']
})
I want a dictionary like:
d={'2020':[12,18,16],
'2025':[5,12,18],
'2030':[8,8,12]
}
I am not able to develop the whole logic:
lst = [list(item.values()) for item in df.to_dict().values()]
dic={}
for items in lst:
for i in items[-1]:
dic[i]=#2000 will hold all the 0th values of other lists and so on
Is there any easier way using pandas ?
Convert Year to index, transpose and then in dict comprehension create lists:
d = {k: list(v) for k, v in df.set_index('Year').T.items()}
print (d)
{'2020': [12, 18, 6], '2025': [5, 12, 18], '2030': [8, 8, 12]}
Or use DataFrame.agg:
d = df.set_index('Year').agg(list, axis=1).to_dict()
print (d)
{'2020': [12, 18, 6], '2025': [5, 12, 18], '2030': [8, 8, 12]}
Try this:
import pandas as pd
data = {'Name': ['Ankit', 'Amit',
'Aishwarya', 'Priyanka'],
'Age': [21, 19, 20, 18],
'Stream': ['Math', 'Commerce',
'Arts', 'Biology'],
'Percentage': [88, 92, 95, 70]}
# Convert the dictionary into DataFrame
df = pd.DataFrame(data, columns=['Name', 'Age',
'Stream', 'Percentage'])

Modyfing 2d array

I'm stuck on trying to modify 2d array... Nothing I try seem to work... I'm trying to write a function that will add a value to its specific location in the numbers column...
import pandas as pd
def twod_array(num):
data = {"group": [-1, 0, 1, 2],
'numbers': [[2], [14, 15], [16, 17], [19, 20, 21]],
}
df = pd.DataFrame(data=data)
print(df)
return 0
Currently it prints this:
group numbers
0 -1 [2]
1 0 [14, 15]
2 1 [16, 17]
3 2 [19, 20, 21]
What I'd like to do is to add a value based on the passed input, so for example if I pass 14.5 as a num, this is the output I'd like to see:
group numbers
0 -1 [2]
1 0 [14,14.5 15]
2 1 [16, 17]
3 2 [19, 20, 21]
Another example:
If I pass 18 as a num:
group numbers
0 -1 [2]
1 0 [14, 15]
2 1 [16, 17, 18]
3 2 [19, 20, 21]
I'm hoping someone can help with this.
df = pd.DataFrame({"group": [-1, 0, 1, 2],
'numbers': [[2], [14, 15], [16, 17], [19, 20, 21]],
})
arr = df['numbers'].to_list()
in_num = 18
for i, sub_arr in enumerate(arr):
for j, num in enumerate(sub_arr):
if arr[i][j]>in_num:
if j!=0: arr[i].insert(j,in_num)
else: arr[i-1].insert(-1 ,in_num)
df['numbers'] = arr

Python alternative to using List as Dictionary Key?

I currently have a dictionary that maps normalized mutual information scores to aligned sites in a multiple sequence alignment, which are stored in a list. However, I've realized that two list may happen to have the same score. Thus only one list will be stored in the dictionary since the score is the key. Clusters should be unique though, so I'm not sure what to do since a my list doesn't have a hash function.
This is what my data looks like. Ideally I would simply like to reverse the keys and values.
{
0.475: [10, 11]
0.434: [12, 14]
0.404: [16, 18]
0.341: [21, 22]
}
You can use comprehension of dictionary here:
d = {0.475: [10, 11], 0.434: [12, 14], 0.404: [16, 18], 0.341: [21, 22]}
print({tuple(d[n]):n for n in d})
Output
{(10, 11): 0.475, (12, 14): 0.434, (16, 18): 0.404, (21, 22): 0.341}
You can't reverse keys and values straightforwardly because lists are unhashable and therefore can't be kept as keys.
Update
In case you have duplicated lists, you might like to create enumeration of repeated lists. You can do it like this:
from collections import defaultdict
d = {0.475: [10, 11], 0.434: [12, 14], 0.404: [16, 18], 0.341: [12, 14]}
new_d = dict()
d_counts = defaultdict(int)
for n in d.keys():
value = tuple(d[n])
new_d[(value, d_counts[value])] = n
d_counts[value] += 1
print(new_d)
Output2
{((10, 11), 0): 0.475, ((12, 14), 0): 0.434, ((16, 18), 0): 0.404, ((12, 14), 1): 0.341}
mydict = {0.475: [10, 11],
0.434: [12, 14],
0.404: [16, 18],
0.341: [21, 22]}
newdict = dict()
for k, v in mydict.items():
newdict[tuple(v)] = k
print(newdict)
# {(10, 11): 0.475, (12, 14): 0.434, (16, 18): 0.404, (21, 22): 0.341}
From this answer, you could try to create a new class from built-in dict:
class Dictlist(dict):
def __setitem__(self, key, value):
try:
self[key]
except KeyError:
super(Dictlist, self).__setitem__(key, [])
self[key].append(value)
So...
>>> d = Dictlist()
>>> d['100'] = [1, 2]
>>> d['100'] = [3, 4]
>>> d
{'100': [[1, 2], [3, 4]]}
Dictionary comprehension should do it with no problem.
my_dict = {0.475: [10, 11], 0.434: [12, 14], 0.404: [16, 18], 0.341: [21, 22]}
my_dict = {my_dict[k]:k for k in my_dict}
Note: if you want to have an if-statement inside of it, you are able to.

Python: function to group number by tens place

Takes a list of numbers and groups the numbers by their tens place, giving every tens place it's own sublist.
ex:
$ group_by_10s([1, 10, 15, 20])
[[1], [10, 15], [20]]
$ group_by_10s([8, 12, 3, 17, 19, 24, 35, 50])
[[3, 8], [12, 17, 19], [24], [35], [], [50]]
my approach:
limiting = 10
ex_limiting = 0
result = []
for num in lst:
row = []
for num in lst:
if num >= ex_limiting and num <= limiting:
row.append(num)
lst.remove(num)
result.append(row)
ex_limiting = limiting
limiting += 10
But it returns [[1], [10, 20]].
What's wrong with my approach and how can I fix it?
You may already have a correct answer, but here's an alternative solution:
def group_by_10s(mylist):
result = []
decade = -1
for i in sorted(mylist):
while i // 10 != decade:
result.append([])
decade += 1
result[-1].append(i)
return result
group_by_10s([8, 12, 3, 17, 19, 24, 35, 50])
#[[3, 8], [12, 17, 19], [24], [35], [], [50]]
It uses only plain Python, no extra modules.
You can use a list comprehension:
def group_by_10s(_d):
d = sorted(_d)
return [[c for c in d if c//10 == i] for i in range(min(_d)//10, (max(_d)//10)+1)]
print(group_by_10s([1, 10, 15, 20]))
print(group_by_10s([8, 12, 3, 17, 19, 24, 35, 50]))
print(group_by_10s(list(range(20))))
Output:
[[1], [10, 15], [20]]
[[3, 8], [12, 17, 19], [24], [35], [], [50]]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]
Credit to advice for not iterating list during loop.
I got this answer at the end, for anyone who wants the answer.
Thanks for support!
def group_by_10s(numbers):
external_loop = int(max(numbers)/10)
limiting = 10
ex_limiting = 0
result = []
for external_loop_count in range(external_loop+1):
row = []
for num in numbers:
if num >= ex_limiting and num < limiting:
row.append(num)
row.sort()
result.append(row)
ex_limiting = limiting
limiting += 10
return(result)
How about this one?
numbers = [8, 12, 3, 17, 19, 24, 35, 50]
def group_by_10s(numbers):
arr = []
for i in range((max(numbers) / 10) + 1):
arr.append([])
numbers.sort()
for number in numbers:
if number < 10:
arr[0].append(number)
else:
index = number / 10
arr[index].append(number)
return arr
print group_by_10s(numbers)
# [[3, 8], [12, 17, 19], [24], [35], [], [50]]
Do not modify the list while you are iterating over it, as when you remove items from it, some items get skipped over. Also change the bounds so that you will only append to row if num < limiting. I would add in a check to make sure the list has elements before adding it to result:
for num in lst:
row = []
for num in lst:
if num >= ex_limiting and num < limiting:
row.append(num)
if len(row) > 0 :
result.append(row)
ex_limiting = limiting
limiting += 10
This will yield:
[[1], [10, 15], [20]]

Flipped an array and reversing every second row

Basically I have a matrix in python 'example' (although much larger). I need to product the array 'example_what_I_want' with some python code. I guess a for loop is in order- but how can I do this?
example=
[1,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20],
[21,22,23,24,25]
example_what_I_want =
[25,24,23,22,21],
[16,17,18,19,20],
[15,14,13,12,11],
[6,7,8,9,10],
[5,4,3,2,1]
So it increments in kind of snake fashion. And the first row must be reversed! and then follow that pattern.
thanks!
I'm assuming example is actually:
example = [[1,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20],
[21,22,23,24,25]]
In which case you could do:
swapped_example = [sublst if idx%2 else sublst[::-1] for
idx,sublst in enumerate(example)][::-1]
Which will give you:
In [5]: swapped_example
Out[5]:
[[25, 24, 23, 22, 21],
[16, 17, 18, 19, 20],
[15, 14, 13, 12, 11],
[6, 7, 8, 9, 10],
[5, 4, 3, 2, 1]]
Or, you can use iter.
a = [[1,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20],
[21,22,23,24,25]]
b = []
rev_a = iter(a[::-1])
while rev_a:
try:
b.append(rev_a.next()[::-1])
b.append(rev_a.next())
except StopIteration:
break
print b
Modified (Did not know that earlier. #Adam),
a = iter(a)
while a:
try:
b.insert(0, a.next()[::-1])
b.insert(0, a.next())
except StopIteration:
break
print b[::-1]

Categories