sorting dictionary by numeric value - python

I have a dict of music genres:
tag_weight = {'industrial': '533621', 'indie': '1971962', 'metal': '1213678', 'heavy metal': '652471', 'japanese': '428102', 'pop': '1873806', 'new wave': '399507', 'black metal': '772132', 'rap': '513024', 'ambient': '1030414', 'alternative': '2059313', 'hard rock': '820796', 'electronic': '2288563', 'blues': '531045', 'folk': '882178', 'classic rock': '1123712', 'alternative rock': '1123488', '90s': '447671', 'indie rock': '850515', 'death metal': '671118', 'electronica': '614494', 'female vocalists': '1557702', 'Soundtrack': '529406', 'dance': '769039', 'funk': '399843', 'psychedelic': '458710', '80s': '751871', 'piano': '409931', 'chillout': '636088', 'post-rock': '426516', 'punk rock': '518515', 'jazz': '1117114', 'seen live': '2097509', 'instrumental': '817816', 'singer-songwriter': '810185', 'metalcore': '444383', 'hardcore': '656111', 'Hip-Hop': '814630', 'hip hop': '394989', 'Classical': '539190', 'punk': '848955', 'soul': '641095', 'british': '667559', 'thrash metal': '465163', 'Progressive metal': '407220', 'rock': '3879179', 'acoustic': '460841', 'german': '409030', 'Progressive rock': '693480', 'experimental': '1010190'}
And I would like to tag them by popularity, that is, sorting by value, from most to less popular.
since dicts are unordered by nature, I must use tuples for that, and I've been trying to use this:
sorted_dict = sorted(tag_weight.items(), key=operator.itemgetter(0), reverse=True)
but it does not seem to be working, because it returns:
[('thrash metal', '465163'), ('soul', '641095'), ('singer-songwriter', '810185'), ('seen live', '2097511'), ('rock', '3879179'), ('rap', '513024'), ('punk rock', '518515'), ('punk', '848955'), ('psychedelic', '458710'), ('post-rock', '426516'), ('pop', '1873806'), ('piano', '409931'), ('new wave', '399507'), ('metalcore', '444383'), ('metal', '1213678'), ('jazz', '1117114'), ('japanese', '428102'), ('instrumental', '817816'), ('industrial', '533621'), ('indie rock', '850515'), ('indie', '1971962'), ('hip hop', '394989'), ('heavy metal', '652471'), ('hardcore', '656111'), ('hard rock', '820796'), ('german', '409030'), ('funk', '399843'), ('folk', '882178'), ('female vocalists', '1557702'), ('experimental', '1010190'), ('electronica', '614494'), ('electronic', '2288563'), ('death metal', '671118'), ('dance', '769039'), ('classic rock', '1123712'), ('chillout', '636088'), ('british', '667559'), ('blues', '531045'), ('black metal', '772132'), ('ambient', '1030414'), ('alternative rock', '1123488'), ('alternative', '2059313'), ('acoustic', '460841'), ('Soundtrack', '529406'), ('Progressive rock', '693480'), ('Progressive metal', '407220'), ('Hip-Hop', '814630'), ('Classical', '539190'), ('90s', '447671'), ('80s', '751871')]
and I guess ('rock', '3879179') should be top on the list.
what am I doing wrong?

Use collections.Counter which is built for this purpose:
import collections
# Convert values to int
tag_weight = {k: int(v) for k, v in tag_weight.items()}
count = collections.Counter(tag_weight)
# Print the top 10
print count.most_common(10)
# Print all, from most popular to least
print count.most_common()
Output of top 10:
[('rock', 3879179), ('electronic', 2288563), ('seen live', 2097509), ('alternative', 2059313), ('indie', 1971962), ('pop', 1873806), ('female vocalists', 1557702), ('metal', 1213678), ('classic rock', 1123712), ('alternative rock', 1123488)]

You're currently sorting on keys, not values, and you also want to do a type cast to integer to avoid sorting lexicographically:
sorted(tag_weight.items(), key=lambda x: int(x[1]), reverse=True)
# ^^^^^^^^ sort on values and do a type cast

Related

Python: How to get a value from randomly selected key in a dictionary

What I'm trying to do here is to get a random choice from a list
races = ['Dragonborn', 'Dwarf', 'Elf', 'Gnome', 'Half-Elf', 'Halfling', 'Half-Orc', 'Human', 'Tiefling']
races_choice = random.choice(races)
and then use that random choice from the list to look at keys in a separate dictionary
subraces = {
'Dwarf': ['Hill Dwarf', 'Mountain Dwarf'],
'Elf': ['High Elf', 'Wood Elf', 'Dark Elf'],
'Halfling': ['Lightfoot', 'Stout'],
'Gnome': ['Forest Gnome', 'Rock Gnome'],
}
and if that key matches the random choice, print a random value from that key.
I've tried a few things, but what I'm currently on is this:
if races_choice == subraces.keys():
print(random.choice(subraces.values[subraces.keys]))
But this returns nothing. I'm a bit at a loss for how to do this.
Thank you.
You can simply use .get on the dictionary.
DEFAULT_VALUE = "default value"
subraces = {
'Dwarf': ['Hill Dwarf', 'Mountain Dwarf'],
'Elf': ['High Elf', 'Wood Elf', 'Dark Elf'],
'Halfling': ['Lightfoot', 'Stout'],
'Gnome': ['Forest Gnome', 'Rock Gnome'],
}
races = ['Dragonborn', 'Dwarf', 'Elf', 'Gnome', 'Half-Elf',
'Halfling',
'Half-Orc', 'Human', 'Tiefling']
races_choice = random.choice(races)
subrace_options = subraces.get(races_choice, DEFAULT_VALUE)
if subrace_options != DEFAULT_VALUE:
index = random.randint(0, (len(subrace_options) - 1))
print(subrace_options[index])
else:
print("No subrace for specified race")
This will yield the name of a subrace from a given race e.g. for Dwarf the output will be a random entry in the list i.e. Hill Dwarf.
The string value in the .get is the default value which will be assigned if the key (the random choice) cannot be found in your map of subraces.
It seems like you can simply set a random int equivalent to the length of items accordingly to the key
import random
races = ['Dragonborn', 'Dwarf', 'Elf', 'Gnome', 'Half-Elf', 'Halfling', 'Half-Orc', 'Human', 'Tiefling']
races_choice = random.choice(races)
subraces = {
'Dwarf': ['Hill Dwarf', 'Mountain Dwarf'],
'Elf': ['High Elf', 'Wood Elf', 'Dark Elf'],
'Halfling': ['Lightfoot', 'Stout'],
'Gnome': ['Forest Gnome', 'Rock Gnome']}
if races_choice in subraces:
print(subraces[races_choice][random.randint(0, len(subraces[races_choice]) - 1)]) # -1 since lists starts from 0, not 1
else:
print('"' + races_choice + '"', 'has no subraces')
you also can try something like this:
from random import choice
print(choice(subraces.get(choice(races),[0])) or 'no matches')

torch/lib/libgomp-d22c30c5.so.1: cannot allocate memory in static TLS block

I installed YoloV5 on my jetson nano. I wanted to execute my object detection code when this error appeared: python3.8/site-packages/torch/lib/libgomp-d22c30c5.so.1: cannot allocate memory in static TLS block.
To fix the problem I tried to put in the bashrc:
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1
It didn't work
Do you have another idea?
Here is my code:
import cv2
import numpy as np
from elements.yolo import OBJ_DETECTION
Object_classes = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
'hair drier', 'toothbrush' ]
Object_colors = list(np.random.rand(80,3)*255)
Object_detector = OBJ_DETECTION('weights/yolov5s.pt', Object_classes)
def gstreamer_pipeline(
capture_width=1280,
capture_height=720,
display_width=1280,
display_height=720,
framerate=60,
flip_method=0,
):
return (
"nvarguscamerasrc ! "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
% (
capture_width,
capture_height,
framerate,
flip_method,
display_width,
display_height,
)
)
print(gstreamer_pipeline(flip_method=0))
cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=0), cv2.CAP_GSTREAMER)
if cap.isOpened():
window_handle = cv2.namedWindow("CSI Camera", cv2.WINDOW_AUTOSIZE)
while cv2.getWindowProperty("CSI Camera", 0) >= 0:
ret, frame = cap.read()
if ret:
objs = Object_detector.detect(frame)
for obj in objs:
label = obj['label']
score = obj['score']
[(xmin,ymin),(xmax,ymax)] = obj['bbox']
color = Object_colors[Object_classes.index(label)]
frame = cv2.rectangle(frame, (xmin,ymin), (xmax,ymax), color, 2)
frame = cv2.putText(frame, f'{label} ({str(score)})', (xmin,ymin), cv2.FONT_HERSHEY_SIMPLEX , 0.75, color, 1, cv2.LINE_AA)
cv2.imshow("CSI Camera", frame)
keyCode = cv2.waitKey(30)
if keyCode == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
else:
print("Unable to open camera")
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1
is not likely to fix your problem.
Because your problem occurred at python3.8/site-packages/torch/lib/libgomp-d22c30c5.so.1.
So required env variable setting is below.
export LD_PRELOAD=<parent path to python3.8>/python3.8/site-packages/torch/lib/libgomp-d22c30c5.so.1
I'm sure there's parent path to python3.8 directory. You should find it and insert it into command above.
how to find it :
How do I find the location of my Python site-packages directory?
By default, it will be /usr/lib. In this case, required command is
export LD_PRELOAD=/usr/lib/python3.8/site-packages/torch/lib/libgomp-d22c30c5.so.1

if a lowercase element is in the list without changing the list to lowercase

I am trying to create a program that replaces any word entered in the input by the word that goes along with it in the dictionary. Here is the dictionary:
slang = {'phone': 'dog and bone', 'queen': 'baked bean', 'suit': 'whistle and flute', 'money': 'bees and honey', 'dead': 'brown bread', 'mate': 'china plate', 'shoes': 'dinky doos', 'telly': 'custard and jelly', 'boots': 'daisy roots', 'road': 'frog and toad', 'head': 'loaf of bread', 'soup': 'loop the loop', 'walk': 'ball and chalk', 'fork': 'roast pork', 'goal': 'sausage roll', 'stairs': 'apples and pears', 'face': 'boat race'}
And here is an example of the output this would make.
Sentence: I called the Queen on the phone
I called the baked bean on the dog and bone
I have tried to code this program, and I have gotten it to print out the output (nearly). I just don't know how to ask if the inputted words are inside the dictionary without replacing the word that is capitalised with a lowercased version.
Here's an example of my output:
Sentence: I called the Queen on the phone
i called the baked bean on the dog and bone
This is the code I have tried and I realise that this issue is arising because I am setting the sentence as lower at the beginning. I have tried to set the 'word' to lower before going into the for loop but this doesn't work either because 'word' is unknown until the for loop.
slang = {'phone': 'dog and bone', 'queen': 'baked bean', 'suit': 'whistle and flute', 'money': 'bees and honey', 'dead': 'brown bread', 'mate': 'china plate', 'shoes': 'dinky doos', 'telly': 'custard and jelly', 'boots': 'daisy roots', 'road': 'frog and toad', 'head': 'loaf of bread', 'soup': 'loop the loop', 'walk': 'ball and chalk', 'fork': 'roast pork', 'goal': 'sausage roll', 'stairs': 'apples and pears', 'face': 'boat race'}
new_sentence = []
sentence = input("Sentence: ").lower()
words_list = sentence.split()
for word in words_list:
if word in slang:
replace = slang[word]
new_sentence.append(replace.lower())
if word not in slang:
new_sentence.append(word)
separator = " "
print(separator.join(new_sentence))
Thank you so much!
Something like the below:
slang = {'phone': 'dog and bone', 'queen': 'baked bean'}
def replace_with_slang(sentence):
words = sentence.split(' ')
temp = []
for word in words:
temp.append(slang.get(word,word))
return ' '.join(temp)
print(replace_with_slang('I called the phone It was the queen '))
You can use list comprehension instead,
slang = {'phone': 'dog and bone', 'queen': 'baked bean', ...}
Sentence = "I called the baked bean on the dog and bone"
print(" ".join(slang.get(x.lower(), x) for x in Sentence.split()))
I called the baked bean on the dog and bone

Trying to conditionally append tuples from a list of tuples to sublists of tuples in a dictionary

I am at a loss on how to achieve what I want, so I'm posting here.
I have a dictionary where each value is a list of tuples (I'll call it dict1), which I am cross referencing against a list of tuples (I'll call it list1). The idea is to append any tuple that is in list1 to each sublist in dict1 if it doesn't already exist in the sublist in the form of (tuple, 0).
Here's what it looks like:
dict1 = {2011: [('Debt collection', 5572),
('Mortgage', 4483),
('Student loan', 431)],
2012: [('Consumer Loan', 480),
('Student loan', 1632),
('Medical loan', 1632),
('Prepaid card', 83)]}
list1 = [('Debt collection', 5572),
('Mortgage', 4483),
('Credit reporting', 3230),
('Checking or savings account', 2068),
('Student loan', 1632),
('Credit card or prepaid card', 1577),
('Bank account or service', 1327),
('Credit card', 1156),
('Consumer Loan', 480)]
I want my code to check if the first part of each tuple in list1 exists in each value list of dict1, and if it doesn't, to append it to each value list in the form of (tuple, 0):
dict1 = {2011: [('Debt collection', 5572),
('Mortgage', 4483),
('Student loan', 431),
('Credit reporting', 0),
('Checking or savings account', 0),
('Credit card or prepaid card', 0),
('Bank account or service', 0),
('Credit card', 0),
('Consumer Loan', 0)],
2012: [('Consumer Loan', 480),
('Student loan', 1632),
('Medical loan', 1632),
('Prepaid card', 83),
('Debt collection', 0),
('Mortgage', 0),
('Credit reporting', 0),
('Checking or savings account', 0),
('Credit card or prepaid card', 0),
('Bank account or service', 0),
('Credit card', 0)]}
I've tried first to extract the first part of each tuple in list1 as a separate list:
available = [tpl[0] for tpl in list1]
Then I attempt the following:
dict1.update(v.extend(tuple((tpl[0],0)) for tpl in v \
for k, v in dict1.items() \
if tpl[0] not in available))
I get the following error:
TypeError Traceback (most recent call last)
<ipython-input-79-53b4b903b6f4> in <module>()
----> 1 dict1.update(v.extend(list(tuple((tpl[0],0)) for tpl in v for k, v in dict1.items()
if tpl[0] not in available)))
<ipython-input-79-53b4b903b6f4> in <genexpr>(.0)
----> 1 dict1.update(v.extend(list(tuple((tpl[0],0)) for tpl in v for k, v in dict1.items()
if tpl[0] not in available)))
TypeError: 'generator' object is not subscriptable
I was looking but didn't find anything that really went over a similar type of case. I'm assuming that I have to use .update for dict1 and also .extend on each list of values (v) in order to deal with each list individually.
You can convert each value into a dict temporarily, use get to ensure a full complement of values, and write it back as a list. This requires no imports:
for k in dict1:
d = dict(dict1[k])
dict1[k] = [(item, d.get(item, 0)) for item, _ in list1]
If you want to have a dictionary in the output, the last line barely changes:
dict1[k] = {item: d.get(item, 0)) for item, _ in list1}
Or, if order matters and you are using Python < 3.6:
dict1 = OrderedDict(item, d.get(item, 0)) for item, _ in list1)
While I would encourage you not to, a one liner is possible:
dict1 = {k: [(item, d.get(item, 0)) for item, _ in list1] for k, d in ((k, dict(v)) for k, v in dict1.items())}
For your problem, dictionaries are easier to handle than lists of tuples. In this case, you can combine mappings via a dictionary comprehension.
from operator import itemgetter
# create dictionary with all keys set to 0
allkeys = dict.fromkeys(map(itemgetter(0), list1), 0)
# for each year, combine dictionary mappings
dict1 = {k: {**allkeys, **dict(v)} for k, v in dict1.items()}
You can, if you wish, convert back to lists of tuples:
res = {k: list(v.items()) for k, v in dict1.items()}
Result for the nested dictionary option:
{2011: {'Debt collection': 5572,
'Mortgage': 4483,
'Credit reporting': 0,
'Checking or savings account': 0,
'Student loan': 431,
'Credit card or prepaid card': 0,
'Bank account or service': 0,
'Credit card': 0,
'Consumer Loan': 0},
2012: {'Debt collection': 0,
'Mortgage': 0,
'Credit reporting': 0,
'Checking or savings account': 0,
'Student loan': 1632,
'Credit card or prepaid card': 0,
'Bank account or service': 0,
'Credit card': 0,
'Consumer Loan': 480,
'Medical loan': 1632,
'Prepaid card': 83}}

Python "not in" index out of range enrror

I am dealing with some kind of problem and i could not find any solution.
My problem is I am controlling a value in a nested list if it is not in another list and deleting it if it is not there but in the not in line it gives me an error like index out of range.
def heroes_updater(men_pref,women):
for i in range(0,len(men_pref)-1):
for j in range(0,len(men_pref[i])-1):
if men_pref[i][j] not in women:
men_pref[i]=men_pref[i][:j]+men_pref[i][j+1:]
example men_pref:
[['Storm', 'Black Widow', 'Scarlet Witch', 'Rouge', 'Mystique', 'Jean Grey', 'Ms. Marvel', 'Gamora', 'Invisible Woman', 'Elektra'], ['Storm', 'Elektra', 'Jean Grey', 'Scarlet Witch', 'Mystique', 'Ms. Marvel', 'Gamora', 'Rouge', 'Black Widow', 'Invisible Woman'], ['Invisible Woman', 'Scarlet Witch', 'Mystique', 'Black Widow', 'Ms. Marvel', 'Elektra', 'Jean Grey', 'Gamora', 'Storm', 'Rouge']]
example women:
['Jean Grey', 'Elektra', 'Mystique', 'Ms. Marvel', 'Rouge']
And the error is :
if men_pref[i][j] not in women:
IndexError: list index out of range
By removing elements from your list, the list gets shorter j is larger than the length of the list. To circumvent this problem, just don't alter the lists, but create a new one:
def heroes_updater(men_pref,women):
result = []
for prefs in men_pref:
new_prefs = []
for pref in prefs:
if pref in women:
new_prefs.append(pref)
result.append(new_prefs)
men_pref[:] = result
or better:
def filter_non_heroes(men_pref,women):
return [
[pref for pref in prefs if pref in women]
for prefs in men_pref
]
You're editing the list you're reading, you must never do that.
With the line men_pref[i]=men_pref[i][:j]+men_pref[i][j+1:]
you're removing an item from the list men_pref[i], but your j variable goes from 0 to the original lenght of the list, so you'll eventually have an index error when you check for men_pref[i][j] if j>len(men_pref[i])
EDIT:
Of, if you want to edit your current list, then you'll have to read it with a backwards index (you start from the last, if it's not on the list of women, you remove it and then continue with the next item):
def heroes_updater(men_pref,women):
for i in range(len(men_pref)-1, -1,-1):
for j in range(len(men_pref[i])-1, -1, -1):
if men_pref[i][j] not in women:
men_pref[i].pop(j)
# An alternative: del(mem_pref[i][j])
Another way would be to use list comprehension:
def heroes_updater(men_pref,women):
for i in range(len(men_pref)-1, -1,-1):
mem_pref[i] = [_w_ for _w_ in mem_pref[i] if _w_ in women]
There are other options, but I'll leave that to you.
That's how you learn.
You can use a set with a list comp, you cannot iterate over and mutate a list as each time you remove an element the list gets smaller and your index is based on what the size of the list when you started the range:
men = [['Storm', 'Black Widow', 'Scarlet Witch', 'Rouge', 'Mystique', 'Jean Grey', 'Ms. Marvel', 'Gamora', 'Invisible Woman', 'Elektra'], ['Storm', 'Elektra', 'Jean Grey', 'Scarlet Witch', 'Mystique', 'Ms. Marvel', 'Gamora', 'Rouge', 'Black Widow', 'Invisible Woman'], ['Invisible Woman', 'Scarlet Witch', 'Mystique', 'Black Widow', 'Ms. Marvel', 'Elektra', 'Jean Grey', 'Gamora', 'Storm', 'Rouge']]
wom = {'Jean Grey', 'Elektra', 'Mystique', 'Ms. Marvel', 'Rouge'}
men[:] = [[ele for ele in sub if ele in wom] for sub in men]
print(men)
Or functionally if order is irrelevant:
men = [['Storm', 'Black Widow', 'Scarlet Witch', 'Rouge', 'Mystique', 'Jean Grey', 'Ms. Marvel', 'Gamora', 'Invisible Woman', 'Elektra'], ['Storm', 'Elektra', 'Jean Grey', 'Scarlet Witch', 'Mystique', 'Ms. Marvel', 'Gamora', 'Rouge', 'Black Widow', 'Invisible Woman'], ['Invisible Woman', 'Scarlet Witch', 'Mystique', 'Black Widow', 'Ms. Marvel', 'Elektra', 'Jean Grey', 'Gamora', 'Storm', 'Rouge']]
wom = {'Jean Grey', 'Elektra', 'Mystique', 'Ms. Marvel', 'Rouge'}
men[:] = map(list,map(wom.intersection, men))
print(men)
You could also start from the end of the list, using your range logic but using range(len(sub)-1,-1, -1) but it is easier to just to use reversed and iterate over the elements themselves:
def heroes_updater(men_pref, women):
for sub in men_pref:
for m in reversed(sub):
if m not in women:
sub.remove(m)

Categories

Resources