Retrieve one value from default dict on python 3 - python-3.x

I have a dict which I populate with data using setdefault method as follows:
if date not in call_dict:
call_dict.setdefault(date, [0, 0]).append(0)
else:
call_dict[date][0] += 1
if x[12] != 'ANSWERED':
call_dict[date][1] += 1
call_dict[date][2] = 100*(call_dict[date][1]/call_dict[date][0])
At the end of this process I have a dict which is structured like this:
{'key' : value0, value1, value2}
Then I have to plot only key and value2 (as value2 is a function of the key) but I can't find the way to access this value.
I tried myDict.values() but it did not work (as expected). I would really like to avoid creating another list/dict/anything because of script performance and also to achieve
that I would still have to reach for the value2 which would solve my problem.
Any ideas how to solve this problem?
Sample values of dict:
{'08:23': [45, 17, 37.77777777777778],
'08:24': [44, 15, 34.090909090909086],
'08:25': [46, 24, 52.17391304347826],
'08:48': [49, 19, 38.775510204081634],

You can get them from the dictionary with a list comprehension:
data = { "2018-07-01": [45, 17, 37.77777777777778],
"2018-07-02": [44, 15, 34.090909090909086],
"2018-07-03": [46, 24, 52.17391304347826],
"2018-07-04": [49, 19, 38.775510204081634]}
xy = [(x,data[x][2]) for x in data.keys()] # extract tuples of (date-key, 3rd value)
print(xy)
Output:
[('2018-07-01', 37.77777777777778), ('2018-07-02', 34.090909090909086),
('2018-07-03', 52.17391304347826), ('2018-07-04', 38.775510204081634)]
If you need them for plotting you might want to do:
x,y = zip(*xy)
print(x)
print(y)
Output:
('2018-07-01', '2018-07-02', '2018-07-03', '2018-07-04') # x
(37.77777777777778, 34.090909090909086, 52.17391304347826, 38.775510204081634) # y
and supply those to your plotting library as x and y data.
Doku: zip(*iterables)

Related

Convert list to a particular format [(123, 123), (345,875)..]

I have the following list:
l = [12, 23,54, 67, 87,98,15, 90, 44,81]
I would like to convert them into pairs with parenthesis. Desired output should look like the following:
[(12, 23),(54, 67), (87,98),(15, 90), (44,81)]
What I tried so far?
print('{}'.format(' '.join('({},)'.format(i) for i in l)))
This does not print the list as pairs. How do I solve this?
l = [12, 23,54, 67, 87,98,15, 90, 44,81]
my=[]
for i in range(0,len(l),2):
my.append(tuple(l[i:i+2]))
print(my)
Rather than for i in l, you'd need to use a range to allow you to set an increment by which to step through. range takes 3 arguments - a starting number, an end number, and (optionally; it defaults to 1) an increment.
Something like this:
tuple_list = [(l[i], l[i+1]) for i in range(0, len(l), 2)]

How to retrieve the target value key for a target value that is contained within a dictionary of lists of values without using a for loop?

I have the following dictionary. Each key contains a list of unique values:
d = {1:[10,11,12],2:[13,14],3:[15,16,17,18],4:[19],5:[20]}
I want to return the key for specified target value as per the example below (this does return the desired result).
keys = list(d.keys())
values_lst = list(d.values())
target_value = 20
for i,values in enumerate(values_lst):
if target_value in values:
index = i
keys[index]
5
However, is there a way to achieve this result without deploying the for loop (at least explicitly). The solution that I have does not feel particularly pythonic.
Thanks!
There always must be a loop somewhere, but you can do it with an one-liner:
d = {1: [10, 11, 12], 2: [13, 14], 3: [15, 16, 17, 18], 4: [19], 5: [20]}
target_value = 20
key = next(k for k, v in d.items() if target_value in v)
print(key)
Prints:
5
A more Pythonic solution, but still with an explicit for:
index = -1
for key, values in d.items():
if target_value in values:
index = key
break
print(d[index])
This may be more readable than a one-liner (as in the other answer), but YMMV.

Python: Use a for loop to get Nth number out of a list

I need to get every 3rd value out of a list and add it to a new list.
This is what I have so far.
def make_reduced_samples(original_samples, skip):
skipped_list = []
for count in range(0, len(original_samples), skip):
skipped_list.append(count)
return skipped_list
skip is equal to 3
I get the indexes and not the value of the numbers in the list.
It gives me [0,3,6]. Which are the indexes in the list and not the value of the indexes.
The example I am given is:
In this list [12,87,234,34,98,11,9,72], you should get [12,34,9].
I cannot use skipped_list = original_samples[::3] in any way.
You need to append the value of the original_samples array at the index. Not the index (count) itself.
def make_reduced_samples(original_samples, skip):
skipped_list = []
for count in range(0, len(original_samples), skip):
skipped_list.append(original_samples[count])
return skipped_list
The correct, most pythonic, and most efficient way to do that is to use slicing.
lst = [12, 87, 234, 34, 98, 11, 9, 72]
skipped_list = lst[::3]
print(skipped_list) # [12, 34, 9]
If the step does not obey a linear relation (which it does here), then you could use a list-comprehension with enumerate to filter on the index.
skipped_list = [x for i, x in enumerate(lst) if i % 3 == 0]
print(skipped_list) # [12, 34, 9]
One liner:
skipped_list = [j for (i,j) in enumerate(original_samples, start=1) if i % 3 == 0]

Python - Insert value to list in a dictionary

I need your help to fix my code. I try to append a value to a list in a dictionary.
def distance(x1, y1, x2, y2):
dis=((x1-x2)**2) + ((y1-y2)**2)
return dis
def cluster_member_formation2(arrCH, arrN, k):
dicCH = dict.fromkeys(arrCH,[])
arrE = []
for j in range(len(arrCH)):
d_nya = distance(arrN[1][0], arrN[1][1], arrN[arrCH[j]][0], arrN[arrCH[j]][1])
arrE.append(d_nya)
minC = min(arrE)
ind = arrE.index(minC)
x = arrCH[ind]
dicCH[x].append(1)
print(arrE, minC, ind, x, dicCH)
arrCH=[23, 35]
arrN={0:[23, 45, 2, 0], 1:[30,21,2,0], 23:[12, 16, 2, 0], 35:[48, 77, 2, 0]}
cluster_member_formation2(arrCH, arrN, 1)
The output:
[349, 3460] 349 0 23 {35: [1], 23: [1]}
I try to calculate the distance between node 1 and all node in arrCH, and then take the minimum distance. In the output show the result of arrE is [349, 3460], so the minimum is 349. 349 has index 0, then I find arrCH with index 0, likes arrCH[0]=23. Finally, I want update dicCH[23].append(1) so the result is
{35: [], 23: [1]}
But, why my code update the all keys, 35 and 23?
I hope someone can help me.
Thank you..
classmethod fromkeys(seq[, value])
Create a new dictionary with keys
from seq and values set to value.
All of your dictionary values reference the same single list instance ([]) which you provide as a value to the fromkeys function.
You could use dictionary comprehension as seen in this answer.
dicCH = {key: [] for key in arrCH}

How to replicate Pandas syntax? (To filter data frames)

How do I implement the syntax for filtering dataframes in Pandas? (df[df.column1 > someValue])
I am trying to make a class that have the same syntax of Pandas when filtering dataframes.
How do I replicate the syntax for a Dataframe df = DataFrame(someData) like this one:
df[df.column1 > someValue]
I implemented the methods __getattr__ and __getitem__ for the syntaxes of
df.column1
df['column1']
But I don't know how to link both together. Also, I could not find the function to copy from Pandas code.
Either an implementation to this problem or the reference to the function in Pandas would be of great help.
Edit:(Solution)
Following the hint on the answers I implemented the __getitem__ function as follows:
from tier tools import compress
def __getitem__(self, name):
"""Get items with [ and ]
"""
#If there is no expression, return a column
if isinstance(name, str):
return self.data[name]
#if there was an expression return the dataframe filtered
elif isinstance(name, list):
ind = list(compress(range(len(name)), name))
temp = DataFrame([[self.data[c].values[i]
for i in ind]
for c in self.columns],
columns=self.columns)
return temp
Note that I also had to implement the comparison methods for my column class (Series).
The full code can be seen here.
You need to implement __getitem__ to take a list of booleans and only return items when True. You will also need to implement the conditional operators (>, ==, etc.) to return that list of booleans, e.g. (proof of concept code):
class A(object):
def __init__(self, data):
self.data = data
def __getitem__(self, key):
return A([d for k, d in zip(key, self.data) if k])
def __gt__(self, value):
return [d > value for d in self.data]
def __repr__(self):
return str(self.__class__) + ' [' + ', '.join(str(d) for d in self.data) + ']'
>>> a = A(list(range(20)))
>>> a
<class '__main__.A'> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> a[a > 5]
<class '__main__.A'> [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
I think you basically want something that just wraps a recarray or structured array.
import numpy as np
myarray = np.array([("Hello",2.5,3),
("World",3.6,2),
('Foobar',2,7)]).T
df = np.core.records.fromarrays(myarray,
names='column1, column2, column3',
formats = 'S8, f8, i8')
print(df)
print(df[df.column3<=3])
While I don't use Pandas myself, the DataFrame seems like it is very similar to a recarray. If you wanted to roll your own, be sure to read about subclassing ndarray. numpy arrays can also be indexed with boolean mask variables such as
myarray = np.array([(1,2.5,3.),
(2,3.6,2.),
(3,2,7.)])
print(myarray[myarray[:,2]<=3.])

Resources