How to convert a list into a multi value dictionary - python

I have a lists of lists that I want to convert into a 4 value dictionary where the first value in each list is the key. So for example the list would be:
[['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]
and i want it to be
{"267-10-7633":[66,85,74,0], "709-40-8165", [71,96,34,0] }

You can use a dictionary comprehension:
lst = [['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]
{k: v for k, *v in lst}
# {'267-10-7633': ['66', '85', '74', 0], '709-40-8165': ['71', '96', '34', 0]}
If you are on python2, seems like you can't use *v to unpack multiple elements:
{x[0]: x[1:] for x in lst}
# {'267-10-7633': ['66', '85', '74', 0], '709-40-8165': ['71', '96', '34', 0]}
Didn't take care of the type conversion here. I guess you can refer to other answers as to how to do that.

A dict comprehension to compile the dictionary with a list comprehension to convert the strings to int:
> lst = [['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]
> {l[0]: [int(x) for x in l[1:]] for l in lst}
{'267-10-7633': [66, 85, 74, 0], '709-40-8165': [71, 96, 34, 0]}

A simple and straight forward solution.
lst = [['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]
# create an empty dict
new_dict = {}
# iterate through the list
for item in lst:
# key is first element in the inner list
# value is second element in the inner list
key = item[0]
value = item[1:]
new_dict[key] = value
print new_dict

List comprehensions is suitable in this case
{element[0]: [int(x) for x in element[1:]] for element in\
[['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]}

A simple approach:
your_list = [['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]
dictionary = {}
for item in your_list:
dictionary[item[0]] = [int(i) for i in item[1:]]
print(dictionary)
With list and dict comprehension:
dictionary = {item[0]: [int(i) for i in item[1:]] for item in your_list}
print(dictionary)
In both cases, output:
{'267-10-7633': [66, 85, 74, 0], '709-40-8165': [71, 96, 34, 0]}

ll = [['267-10-7633', '66', '85', '74', 0], ['709-40-8165', '71', '96', '34', 0]]
mydict = {}
for item in ll:
key,*values = item
mydict[key] = values
print(mydict)

Related

How to transform index values into columns using Pandas?

I have a dictionary like this:
my_dict = {'RuleSet': {'0': {'RuleSetID': '0',
'RuleSetName': 'Allgemein',
'Rules': [{'RulesID': '10',
'RuleName': 'Gemeinde Seiten',
'GroupHits': '2',
'KeyWordGroups': ['100', '101', '102']}]},
'1': {'RuleSetID': '1',
'RuleSetName': 'Portale Berlin',
'Rules': [{'RulesID': '11',
'RuleName': 'Portale Berlin',
'GroupHits': '4',
'KeyWordGroups': ['100', '101', '102', '107']}]},
'6': {'RuleSetID': '6',
'RuleSetName': 'Zwangsvollstr. Berlin',
'Rules': [{'RulesID': '23',
'RuleName': 'Zwangsvollstr. Berlin',
'GroupHits': '1',
'KeyWordGroups': ['100', '101']}]}}}
When using this code snippet it can be transformed into a dataframe:
rules_pd = pd.DataFrame(my_dict['RuleSet'])
rules_pd
The result is:
I would like to make it look like this:
Does anyone know how to tackle this challenge?
Doing from_dict with index
out = pd.DataFrame.from_dict(my_dict['RuleSet'],'index')
Out[692]:
RuleSetID ... Rules
0 0 ... [{'RulesID': '10', 'RuleName': 'Gemeinde Seite...
1 1 ... [{'RulesID': '11', 'RuleName': 'Portale Berlin...
6 6 ... [{'RulesID': '23', 'RuleName': 'Zwangsvollstr....
[3 rows x 3 columns]
#out.columns
#Out[693]: Index(['RuleSetID', 'RuleSetName', 'Rules'], dtype='object')
You could try use Transpose()
rules_pd = pd.DataFrame(my_dict['RuleSet']).transpose()
print(rules_pd)

Mapping items in one list to the items in another list

I have two lists in Python and I'm trying to map the values of one to the other.
List 1 (coordinates):
['7,16', '71,84', '72,48', '36,52', '75,36', '52,28', '76,44', '11,69', '56,35',
'15,21', '32,74', '88,32', '10,74', '61,34', '51,85', '10,75', '55,96',
'94,12', '34,64', '71,59', '76,75', '25,16', '54,100', '62,1', '60,85',
'16,32', '14,77', '40,78', '2,60', '71,4', '78,91', '100,98', '42,32', '37,49',
'49,34', '3,5', '42,77', '39,60', '38,77', '49,40', '40,53', '57,48', '14,99',
'66,67', '10,9', '97,3', '66,76', '86,68', '10,60', '8,87']
List 2 (index):
[3, 2, 3, 3, 3, 3, 3, 1, 3, 3, 2, 3, 1, 3, 2, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
1, 2, 1, 3, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3, 1, 2, 3, 3, 2, 2, 1, 1]
For the output, I need to have something like:
cluster_1: [x, y], [a,b]...
cluster_2: [c, d], [e, f]...
cluster_3: [g, h], [o, j]...
I tried doing this in a dictionary, but I can only get it to put in the last coordinate in the for loop for each value. It also always outputs keys starting from 0, and I'm looking to label them starting from 1.
for i in range(len(patients)):
# other stuff
k = 3
for b in range(k):
if cluster == (k - b):
dct['cluster_%s' % b] = patients[i]
which outputs:
{'cluster_0': '97,3', 'cluster_1': '86,68', 'cluster_2': '8,87'}
I've tried using dct['cluster_%s' % b].append(patients[i]) but I get a key error on cluster_0. Any help would be much appreciated!
You can zip your indices and coordinates, then loop over them element-wise and populate a dictionary based on the index.
clusters = {}
for idx, coord in zip(index, coords):
if idx in clusters:
clusters[idx].append(coord.split(','))
else:
clusters[idx] = [coord.split(',')]
result, where clusters[i] refers the the i-th cluster.
>>> clusters
{
3: [['7', '16'], ['72', '48'], ['36', '52'], ['75', '36'], ['52', '28'], ['76', '44'], ['56', '35'], ['15', '21'], ['88', '32'], ['61', '34'], ['94', '12'], ['71', '59'], ['25', '16'], ['62', '1'], ['16', '32'], ['71', '4'], ['42', '32'], ['37', '49'], ['49', '34'], ['3', '5'], ['49', '40'], ['40', '53'], ['57', '48'], ['10', '9'], ['97', '3']],
2: [['71', '84'], ['32', '74'], ['51', '85'], ['55', '96'], ['34', '64'], ['76', '75'], ['54', '100'], ['60', '85'], ['40', '78'], ['78', '91'], ['100', '98'], ['42', '77'], ['39', '60'], ['38', '77'], ['66', '67'], ['66', '76'], ['86', '68']],
1: [['11', '69'], ['10', '74'], ['10', '75'], ['14', '77'], ['2', '60'], ['14', '99'], ['10', '60'], ['8', '87']]
}
You could use defaultdict along with zip:
from collections import defaultdict
clusters = defaultdict(list)
for id, value in zip(cluster_indices, values):
clusters[id].append(value.split(","))
print(dict(clusters)) # {3: [['7', '16'], ['72', '48'], ...
A defaultdict can be converted to a dict with dict(clusters). However, this may not be necessary since defaultdict basically extends dict.
Note: If you need int values, then you may replace value.split(",") with [int(v) for v in value.split(",")] or list(map(int, value.split(","))). Casting them already at this point will save you an iteration later.
from collections import defaultdict
clusters = defaultdict(list)
for id, value in zip(cluster_indices, values):
clusters[id].append([int(v) for v in value.split(",")])
print(dict(clusters)) # {3: [[7, 16], [72, 48], ...
The group-by behaviour extracted to a function groupby (using a lambda function to allow any kind of transformation) so it can be reused:
from collections import defaultdict
def groupby(indices, values, map_fn):
grouped = defaultdict(list)
for id, value in zip(indices, values):
grouped[id].append(map_fn(id, value))
return dict(grouped)
clusters = groupby(cluster_indices, values, lambda _, value: value.split(","))
print(clusters) # {3: [['7', '16'], ['72', '48'], ...
Here just another way by using itertools.groupby:
from itertools import groupby
from operator import itemgetter
data = sorted(zip(cluster_indices, values), key=itemgetter(0))
grouped = groupby(data, key=itemgetter(0))
clusters = {
cluster: [value[1].split(",") for value in list(values)]
for cluster, values in grouped
}
print(clusters) # {3: [['7', '16'], ['72', '48'], ...
However, I would use the defaultdict approach above or Cory Kramer's answer as it is more simple and easier to read (and therefore preferable)!

Convert a matrix from string to integer

I'm trying to change a matrix of numbers from string to integer but it just doesn't work.
for element in list:
for i in element:
i = int(i)
What am I doing wrong?
Edit:
This is the whole code:
import numpy as np
t_list = []
t_list = np.array(t_list)
list_rains_per_months = [['63', '65', '50', '77', '66', '69'],
['65', '65', '67', '50', '54', '58'],
['77', '73', '80', '83', '89', '100'],
['90', '85', '90', '90', '84', '90'],
['129', '113', '120', '135', '117', '130'],
['99', '116', '114', '111', '119', '100'],
['105', '98', '112', '113', '102', '100'],
['131', '120', '111', '141', '130', '126'],
['85', '101', '88', '89', '94', '91'],
['122', '103', '119', '98', '101', '107'],
['121', '101', '104', '121', '115', '104'],
['67', '44', '58', '61', '64', '58']]
for element in t_list:
for i in element:
i = int(i)
I apologize for any mistakes, I'm new to python
What you're doing wrong, is that you're not changing the list or any list element: the 'i' inside the loop starts by pointing to each element of the list, then you make it point to something else, but that doesn't affect your list (also, avoid using 'list' as an identifier, it's an existing type, that's asking for trouble).
One way to do it is with list comprehensions. Assuming your matrix is a list of (inner) lists, for example:
a_list = [["3", "56", "78"], ["2", "39", "60"], ["87", "9", "71"]]
then two nested list comprehensions should do the trick:
a_list = [[int(i) for i in inner_list] for inner_list in a_list]
This builds a new list, formed by going over your initial list, applying the change you want, and saving it a another (or the same) list.
In numpy you do it that way.
import numpy as np
list_rains_per_months = [['63', '65', '50', '77', '66', '69'],
['65', '65', '67', '50', '54', '58'],
['77', '73', '80', '83', '89', '100'],
['90', '85', '90', '90', '84', '90'],
['129', '113', '120', '135', '117', '130'],
['99', '116', '114', '111', '119', '100'],
['105', '98', '112', '113', '102', '100'],
['131', '120', '111', '141', '130', '126'],
['85', '101', '88', '89', '94', '91'],
['122', '103', '119', '98', '101', '107'],
['121', '101', '104', '121', '115', '104'],
['67', '44', '58', '61', '64', '58']]
list_rains_per_months = np.array(list_rains_per_months)
myfunc = np.vectorize(lambda x: int(x))
list_rains_per_months = myfunc(list_rains_per_months)
print(list_rains_per_months)
Output
[[ 63 65 50 77 66 69]
[ 65 65 67 50 54 58]
[ 77 73 80 83 89 100]
[ 90 85 90 90 84 90]
[129 113 120 135 117 130]
[ 99 116 114 111 119 100]
[105 98 112 113 102 100]
[131 120 111 141 130 126]
[ 85 101 88 89 94 91]
[122 103 119 98 101 107]
[121 101 104 121 115 104]
[ 67 44 58 61 64 58]]
You could use enumerate object in loops:
list = [["12", "10", "0"],
["0", "33", "60"]]
for h, i in enumerate(list):
for j, k in enumerate(i):
list[h][j] = int(k)
print(list)
Could also just map each row's values to int:
for row in list_rains_per_months:
row[:] = map(int, row)
Note that I assign to row[:], i.e., into the row and thus into the matrix. If I assigned to row instead, I'd have the same problem as you with your i: I'd only assign to the variable, not into the row/matrix.

Values of dictionary = sum of 2dlist at i

I have the following 2d list and dictionary:
List2d = [['1', '55', '32', '667' ],
['43', '76', '55', '100'],
['23', '70', '15', '300']]
dictionary = {'New York':0, "London": 0, "Tokyo": 0, "Toronto": 0 }
How do I replace all the values of the dictionary with sums of the columns in List2d? So dictionary will look like this:
dictionary= {'New York' : 67, 'London': 201, 'Tokyo': 102, 'Toronto': 1067}
#67 comes from adding up first column (1+43+23) in 'List2d'
#201 comes from adding up second column (55+76+70) in 'List2d'
#102 comes from adding up third column (32+55+15) in 'List2d'
#1067 comes from adding up fourth column (667+100+300) in 'List2d'
Since Python 3.7, keys in dict are ordered.
You can use enumerate in order to keep track of the position of the element in the dict while iterating over it. Then, you use the i as an index on each row of the 2d list, convert each value to int and do a sum of the result.
List2d = [['1', '55', '32', '667' ],
['43', '76', '55', '100'],
['23', '70', '15', '300']]
dictionary = {'New York':0, "London": 0, "Tokyo": 0, "Toronto": 0 }
for i, city in enumerate(dictionary.keys()):
dictionary[city] = sum(int(row[i]) for row in List2d)
print(dictionary)
# {'New York': 67, 'London': 201, 'Tokyo': 102, 'Toronto': 1067}
Use pandas
#!pip install pandas
import pandas as pd
pd.DataFrame(List2d, columns=dictionary.keys()).astype(int).sum(axis=0).to_dict()
output:
{'New York': 67, 'London': 201, 'Tokyo': 102, 'Toronto': 1067}

Python - insert into list

I get an array form a csv file and I get an list that looks like
my_list = ["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', '', '', '', '', '', '', '', '']
And now I want to fill the spots where there is '' with an array of items that is that length, lets say the array I want to put in there is
new_array = [1,2,3,4,5,6,7,8]
here is what I am trying but it doesn't work.
i = 0
for item in new_array:
index = 8+i
print item
my_list.insert(index, item)
i += 0
It doesn't change anything my_list is just the same?
How can I change this?
Thanks
Try this:
i = 8
for item in new_array:
my_list[i] = item # you want to replace the value
i += 1 # you forgot to increment the variable
You weren't incrementing the variable i, and insert() moves the items to the right, it doesn't substitute them. Of course, a more idiomatic solution would be:
my_list = my_list[:8] + new_array
my_list = ["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', '', '', '', '', '', '', '', '']
new_array = [1,2,3,4,5,6,7,8]
i = 0
for item in new_array:
index = 8+i
print item
my_list.remove('')
my_list.insert(index, item)
i += 1
print my_list
output:
1
2
3
4
5
6
7
8
["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', 1, 2, 3, 4, 5, 6, 7, 8]
Something like this:
new_iter = iter(new_array)
my_list = [i if i != '' else next(new_iter) for i in my_list]
print(my_list)
This code will work with '' (empty strings) starting at any index:
my_list = ["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', '', '', '', '', '', '', '', '']
starts_at = my_list.index('')
amount_of_empty_strings = 0
for i, item in enumerate(my_list):
if item.strip() == "":
my_list[amount_of_empty_strings+starts_at] = amount_of_empty_strings+1
amount_of_empty_strings+=1
print my_list
Output:
["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', 1, 2, 3, 4, 5, 6, 7, 8]
Using list comprehension
>>> new_array = [1,2,3,4,5,6,7,8]
>>> new_array.reverse()
>>> new_array
[8, 7, 6, 5, 4, 3, 2, 1]
>>> [new_array.pop() if item is '' else item for item in my_list]
["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', 1, 2, 3, 4, 5, 6, 7, 8]
OR
>>> from collections import deque
>>> new_array = deque([1,2,3,4,5,6,7,8])
>>> [new_array.popleft() if item is '' else item for item in my_list]
["Nov '15", '75', '49', '124', '62', '18', '80', '64.5', 1, 2, 3, 4, 5, 6, 7, 8]

Categories