I have a large list, which I separated into small sized lists which have elements of occurrences of 1s and 0s, randomly.
Also, the first two lists are made with different parameters from the last two.
Example:
list_of_lists[0] =[1,0,1,1,1,0,1,1,1,0]
list_of_lists[1] =[0,0,0,0,0,0,0,0,0,0]
list_of_lists[2] =[1,1,1,1,1,1,1,1,1,1]
list_of_lists[3] =[0,0,1,1,1,1,1,1,1,0]
I would like to count the occurrences of 1s and 0s in each list, and append them into a dictionary to plot the occurrences.
My trial is as follows:
counts_each = dict()
for i in range(4): #all 4 lists
for k in list_of_lists[i]: #elements of the lists
counts_each[k] = counts_each.get(k, 0) + 1
print(counts_each)
which calculates the general occurrences of the 1s and 0s for the al lists:
{0: 16, 1: 24}
If I do:
list_counts = []
for i in range(4):
counts_each = dict()
for k in list_of_lists[i]:
counts_each[k] = counts_each.get(k, 0) + 1
list_counts.append(counts_each)
print(list_counts)
It does not accumulate all of the counts:
[{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7}]
I would be glad to have some insights of what I am doing wrong.
Thank you.
You can let the collections module do all the counting work for you.
from collections import Counter
list_of_lists = [[] for _ in range(4)]
list_of_lists[0] =[1,0,1,1,1,0,1,1,1,0]
list_of_lists[1] =[0,0,0,0,0,0,0,0,0,0]
list_of_lists[2] =[1,1,1,1,1,1,1,1,1,1]
list_of_lists[3] =[0,0,1,1,1,1,1,1,1,0]
counters = [Counter(l) for l in list_of_lists]
print(*counters, sep="\n")
OUTPUT
Counter({1: 7, 0: 3})
Counter({0: 10})
Counter({1: 10})
Counter({1: 7, 0: 3})
You could use a Dict Comprehension, given your nested list:
list_of_lists = [[1,0,1,1,1,0,1,1,1,0], [0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,1,1,1,1], [0,0,1,1,1,1,1,1,1,0]]
use it in this way:
{ idx: {0: lst.count(0), 1: lst.count(1)} for idx, lst in enumerate(list_of_lists) }
#=> {0: {0: 3, 1: 7}, 1: {0: 10, 1: 0}, 2: {0: 0, 1: 10}, 3: {0: 3, 1: 7}}
In the above case I used the index as a key, but you could just use a list comprehension to get a list of dictionaries:
[ {0: lst.count(0), 1: lst.count(1)} for lst in list_of_lists ]
#=> [{0: 3, 1: 7}, {0: 10, 1: 0}, {0: 0, 1: 10}, {0: 3, 1: 7}]
Chris Doyle's answer is excellent, but perhaps your goal is to understand the problem with your solution, specifically.
You have not included your expected output. If I am correct that your issue with your current solution is the repetition of the counts, and you want an output like this:
[{1: 7, 0: 3}, {0: 10}, {1: 10}, {0: 3, 1: 7}]
Then the issue appears to be with the indenting of the line list_counts.append(counts_each). You are doing this each time through the k loop (looping through the items in the list) when I think you want to do it only after finishing the count for a given list:
list_counts = []
for i in range(4):
counts_each = dict()
for k in list_of_lists[i]:
counts_each[k] = counts_each.get(k, 0) + 1
list_counts.append(counts_each)
print(list_counts)
Related
I have a table of an "Id" column and multiple integer columns that I want to convert to categorical variables. Therefore, I want to apply this transformation only to those multiple integer columns, but leave the ID column unchanged.
All the other methods involve dropping the ID column. How do I do this without dropping the ID column?
This is the current code i have:
df= df.loc[:, df.columns != 'Id'].apply(lambda x: x.astype('category'))
Sample dataframe:
{'Id': {0: 0, 1: 1, 2: 2, 3: 3, 4: 4},
'Foundation': {0: 2, 1: 1, 2: 2, 3: 0, 4: 2},
'GarageFinish': {0: 1, 1: 1, 2: 1, 3: 2, 4: 1},
'LandSlope': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0},
'LotConfig': {0: 4, 1: 2, 2: 4, 3: 0, 4: 2},
'GarageQual': {0: 4, 1: 4, 2: 4, 3: 4, 4: 4},
'GarageCond': {0: 4, 1: 4, 2: 4, 3: 4, 4: 4},
'LandContour': {0: 3, 1: 3, 2: 3, 3: 3, 4: 3},
'Utilities': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0},
'GarageType': {0: 1, 1: 1, 2: 1, 3: 5, 4: 1},
'LotShape': {0: 3, 1: 3, 2: 0, 3: 0, 4: 0},
'Alley': {0: 2, 1: 2, 2: 2, 3: 2, 4: 2},
'Street': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
'PoolQC': {0: 3, 1: 3, 2: 3, 3: 3, 4: 3},
'Fence': {0: 4, 1: 4, 2: 4, 3: 4, 4: 4},
'MiscFeature': {0: 4, 1: 4, 2: 4, 3: 4, 4: 4},
'MSZoning': {0: 3, 1: 3, 2: 3, 3: 3, 4: 3},
'SaleType': {0: 8, 1: 8, 2: 8, 3: 8, 4: 8},
'PavedDrive': {0: 2, 1: 2, 2: 2, 3: 2, 4: 2},
'FireplaceQu': {0: 5, 1: 4, 2: 4, 3: 2, 4: 4},
'Condition1': {0: 2, 1: 1, 2: 2, 3: 2, 4: 2},
'Functional': {0: 6, 1: 6, 2: 6, 3: 6, 4: 6},
'BsmtQual': {0: 2, 1: 2, 2: 2, 3: 3, 4: 2},
'BsmtCond': {0: 3, 1: 3, 2: 3, 3: 1, 4: 3},
'BsmtExposure': {0: 3, 1: 1, 2: 2, 3: 3, 4: 0},
'BsmtFinType1': {0: 2, 1: 0, 2: 2, 3: 0, 4: 2},
'ExterQual': {0: 2, 1: 3, 2: 2, 3: 3, 4: 2},
'BsmtFinType2': {0: 5, 1: 5, 2: 5, 3: 5, 4: 5},
'MasVnrType': {0: 1, 1: 2, 2: 1, 3: 2, 4: 1},
'Exterior2nd': {0: 13, 1: 8, 2: 13, 3: 15, 4: 13},
'Heating': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
'Neighborhood': {0: 5, 1: 24, 2: 5, 3: 6, 4: 15},
'SaleCondition': {0: 4, 1: 4, 2: 4, 3: 0, 4: 4},
'Electrical': {0: 4, 1: 4, 2: 4, 3: 4, 4: 4},
'Exterior1st': {0: 12, 1: 8, 2: 12, 3: 13, 4: 12},
'RoofMatl': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
'RoofStyle': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
'HouseStyle': {0: 5, 1: 2, 2: 5, 3: 5, 4: 5},
'BldgType': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0},
'Condition2': {0: 2, 1: 2, 2: 2, 3: 2, 4: 2},
'KitchenQual': {0: 2, 1: 3, 2: 2, 3: 2, 4: 2},
'ExterCond': {0: 4, 1: 4, 2: 4, 3: 4, 4: 4},
'CentralAir': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
'HeatingQC': {0: 0, 1: 0, 2: 0, 3: 2, 4: 0}}
One way to do this is by isolating the Id column and then joining the converted columns:
df = df[['Id']].join(
df.loc[:, df.columns != 'Id'].astype('category')
)
Another way is to try:
df = df.groupby('Id').transform(lambda x: pd.Categorical(x)).reset_index(names = 'id')
I think the easier way would be to use astype directly, and provide a generated dictionary.
cast_df = df.astype({col: 'category' for col in df if col != 'Id'})
It's probably more performant than the other solutions too.
This is my code:
a=[1,2,3,4,5,6,7]
b=[8,9,10,11,12,13,14]
c=[{i:j} for i in a for j in b]
print(c)
Output is
[{1: 8}, {1: 9}, {1: 10}, {1: 11}, {1: 12}, {1: 13}, {1: 14}, {2: 8}, {2: 9}, {2: 10}, {2: 11}, {2: 12}, {2: 13}, {2: 14}, {3: 8}, {3: 9}, {3: 10}, {3: 11}, {3: 12}, {3: 13}, {3: 14}, {4: 8}, {4: 9}, {4: 10}, {4: 11}, {4: 12}, {4: 13}, {4: 14}, {5: 8}, {5: 9}, {5: 10}, {5: 11}, {5: 12}, {5: 13}, {5: 14}, {6: 8}, {6: 9}, {6: 10}, {6: 11}, {6: 12}, {6: 13}, {6: 14}, {7: 8}, {7: 9}, {7: 10}, {7: 11}, {7: 12}, {7: 13}, {7: 14}]
But I want like:
[{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
How to achieve this?
To pair several list together you need to use zip operation zip(a, b),
You may use dict comprehension notation or dict constructor
Wrap in an array if needed
c = dict(zip(a, b)) # {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
c = [dict(zip(a, b))] # [{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
c = {i: j for i, j in zip(a, b)} # {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
c = [{i: j for i, j in zip(a, b)}] # [{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
Your notation [{:} for _ in _] was creating a dict for each iteration, resulting in mulitple dicts in a list [{}, {}, {}]
Use dict with zip
Ex:
a=[1,2,3,4,5,6,7]
b=[8,9,10,11,12,13,14]
print(dict(zip(a, b)))
# --> {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
My code is the following:
import itertools
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
names = [item[0] for item in lists]
for x in lists:
del x[0]
answer = {name:set(L) for name,L in zip(names, lists)}
which gives me:
{0: {1}, 1: {2, 8}, 3: {4}, 4: {2}, 2: {5}, 5: {6, 7}, 8: {9, 10, 11, 12}}
But what I want to have is to add a key of a previous items for each of the entries. What I want is to have
{0:{1},1:{0,2,8},3:{1,4},4:{3,2} (...)}
Futhermore I would like to twist it a little I mean as a key I want to have each number I have on a list e.g. as I have 5:{6,7} i want to have as well 6:{5,7} and 7:{5,6} obviously i should not have any duplicates.
My question is how could i achieve this?
To make myself clearer I want to visualize a the following graph:
I find it unlikely you would want to make a dict of all permutations of each list as you have a duplicate numbers in a couple of them so possibly making a list of all the dicts (of which being the permutations of each list) then you could do this:
from itertools import permutations
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
answer = [{k:set(v) for k, *v in perms} for perms in map(permutations, lists)]
Output for this being:
[{0: {1}, 1: {0}}, {1: {8, 2}, 2: {8, 1}, 8: {1, 2}}, {3: {4}, 4: {3}}, {4: {2}, 2: {4}}, {2: {5}, 5: {2}}, {5: {6, 7}, 6: {5, 7}, 7: {5, 6}}, {8: {9, 10, 11, 12}, 9: {8, 10, 11, 12}, 10: {8, 9, 11, 12}, 11: {8, 9, 10, 12}, 12: {8, 9, 10, 11}}]
Otherwise if you don’t mind losing some of the values to being overwritten then you could use this comprehension
answer = {k:set(v) for perms in map(permutations, lists) for k, *v in perms}
Output of this being:
{0: {1}, 1: {8, 2}, 2: {5}, 8: {9, 10, 11, 12}, 3: {4}, 4: {2}, 5: {6, 7}, 6: {5, 7}, 7: {5, 6}, 9: {8, 10, 11, 12}, 10: {8, 9, 11, 12}, 11: {8, 9, 10, 12}, 12: {8, 9, 10, 11}}
You could do this with defaultdict from collections:
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
from collections import defaultdict
edges = [ (V[0],Vn) for V in lists for Vn in V[1:] ]
result = next( d for d in [defaultdict(set)] if [d[a].add(b) or d[b].add(a) for a,b in edges])
print( dict(result))
# {0: {1}, 1: {0, 8, 2}, 2: {1, 4, 5}, 8: {1, 9, 10, 11, 12}, 3: {4}, 4: {2, 3}, 5: {2, 6, 7}, 6: {5}, 7: {5}, 9: {8}, 10: {8}, 11: {8}, 12: {8}}
You can use dict comprehension:
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
answer = {lists[i][0]: set(([lists[i - 1][0]] if i > 0 else []) + lists[i][1:]) for i in range(len(lists))}
First of all, you don't need to build a names list: destructuring assignment will do the trick.
>>> lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
>>> answer = {name:set(L) for name,*L in lists}
>>> answer
{0: {1}, 1: {8, 2}, 3: {4}, 4: {2}, 2: {5}, 5: {6, 7}, 8: {9, 10, 11, 12}}
Now, you want to add the previous name when you compute the current name:list. You just have to zip the list with itself to get the expected result:
>>> answer = {name2:set([name1]+L2) for (name1,*L1), (name2,*L2) in zip([[lists[0][1]]]+lists, lists)}
>>> answer
{0: {1}, 1: {0, 8, 2}, 3: {1, 4}, 4: {2, 3}, 2: {4, 5}, 5: {2, 6, 7}, 8: {5, 9, 10, 11, 12}}
The trick is to add an element before the first version of the list that will not change the first name:list. If you use [lists[0][1]], the first name1 is part of the first list2 and the set will be unchanged.
i want to create a dictionary of an array of dictionaries from a list of node pairs and their weight.
nets = pd.read_table('data/nodes.txt', header = None)
bb = np.array(nets).tolist()
graph = collections.defaultdict(dict)
for row in bb:
graph[row[0]][row[1]]=row[2]
graph[row[1]][row[0]] = row[2]
print(dict(graph))
which resulted in this dictionary
{0: {1: 2, 2: 3, 3: 6, 7: 8}, 1: {0: 2, 2: 5, 4: 7}, 2: {0: 3, 1: 5, 11: 5, `5: 4}, 3: {0: 6, 11: 4, 6: 2}, 4: {1: 7}, 5: {8: 3, 2: 4}, 6: {9: 3, 3: 2}, 7: {0: 8}, 8: {5: 3}, 9: {10: 6, 6: 3}, 10: {9: 6}, 11: {2: 5, 3: 4}}`
and want a it in this form.
{0: [{1: 2}, {2: 3}, {3: 6}, {7: 8}],
1: [{0: 2}, {2: 5}, {4: 7}],
2: [{0: 3}, {1: 5}, {11: 5}, {5: 4}],
3: [{0: 6}, {11: 4}, {6: 2}],
4: [{1: 7}],
5: [{8: 3}, {2: 4}],
6: [{9: 3}, {3: 2}],
7: [{0: 8}, 8: {5: 3}],
9: [{10: 6}, {6: 3}],
10: [{9: 6}],
11: [{2: 5}, {3: 4}]}
You can do this pretty easily if you really want to, though I'd look carefully at where you're going to use this data structure to see if your existing more logical structure could be made to work instead.
Anyway, here's a quick implementation that should do what you want:
graph = collections.defaultdict(list)
for row in bb:
graph[row[0]].append({row[1]: row[2]})
graph[row[1]].append({row[0]: row[2]})
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q:
for x,y in d.values():
newList.append(d[word].x())
What I'm attempting to do here is get each first part of the number pairs and put into the list when it corresponds to a word in q. So I'm expecting newList to be [1,2,3,4,1,2,3].
I am getting ValueError: too many values to unpack (expected 2). How should I be doing this?
The values in the dictionary 'd' are actually of type dictionary themselves, not tuples. I think you may want to reorganize this a bit.
for word in q.split(" "):
if word in d:
child_dict = d[word]
for key in child_dict:
newList.append(key)
Is this what you're looking for?
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q.split(' '):
newList.extend(list(d[word].keys()))
print(newList)
It prints out [1, 2, 3, 4, 1, 2, 3]
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q.split(' '):
if word in d:
newList.extend([i for i in d[word]])
print(newList)