Numpy probabilities
Question:
I was just wondering why I’m getting an error from running the code below. I’m trying to use numpy to do probabilities for a text-based game. The code below is not what will be in the game itself. This is just for testing purposes and to learn. Thanks for your answers in advance, and please go easy on me.
from numpy.random import choice
class container:
def __init__(self):
self.inv = {'common': ['blunt sword', 'blunt axe'], 'uncommon': ['Dynasty bow', 'Axe', 'Sword'], 'rare': ['Sharp axe'], 'epic': ['Great Sword']}
self.probabilities = {"common": 50, 'uncommon':25, 'rare': 10, 'epic': 3}
self.item = choice(self.inv(choice(self.probabilities.keys(), p=self.probabilities.values())))
def open(self):
return f'You loot {self.item}'
loot = container().open()
print(loot)
Error:
Traceback (most recent call last):
File "mtrand.pyx", line 1115, in mtrand.RandomState.choice
TypeError: 'dict_keys' object cannot be interpreted as an integer
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 14, in <module>
loot = container().open()
File "test.py", line 8, in __init__
self.item = choice(self.inv(choice(self.probabilities.keys(), p=self.probabilities.values())))
File "mtrand.pyx", line 1117, in mtrand.RandomState.choice
ValueError: 'a' must be 1-dimensional or an integer
Answers:
As per the documentation of np.random.choice it takes in a 1D array or int a
and a probability vector p
whose length is equal to length of a
and sums to one. In your case you are feeding probabilities.keys()
and inv.keys()
which are of type dict_keys
. Also, your probability vector doesn’t sum to 1. one way to convert the probability vector to the required format is to divide it by the sum of it. I have make the necessary changes to the code
from numpy.random import choice
class container:
def __init__(self):
self.inv = {'common': ['blunt sword', 'blunt axe'], 'uncommon': ['Dynasty bow', 'Axe', 'Sword'], 'rare': ['Sharp axe'], 'epic': ['Great Sword']}
self.probabilities = {"common": 50, 'uncommon':25, 'rare': 10, 'epic': 3}
self.convert_prob_vector()
self.item = choice(self.inv[choice(list(self.probabilities.keys()), p=self.probabilities_new)])
def convert_prob_vector(self):
self.probabilities_new = [x / sum(self.probabilities.values()) for x in self.probabilities.values()]
def open(self):
return f'You loot {self.item}'
loot = container().open()
print(loot)
Sample Output
You loot Dynasty bow
I was just wondering why I’m getting an error from running the code below. I’m trying to use numpy to do probabilities for a text-based game. The code below is not what will be in the game itself. This is just for testing purposes and to learn. Thanks for your answers in advance, and please go easy on me.
from numpy.random import choice
class container:
def __init__(self):
self.inv = {'common': ['blunt sword', 'blunt axe'], 'uncommon': ['Dynasty bow', 'Axe', 'Sword'], 'rare': ['Sharp axe'], 'epic': ['Great Sword']}
self.probabilities = {"common": 50, 'uncommon':25, 'rare': 10, 'epic': 3}
self.item = choice(self.inv(choice(self.probabilities.keys(), p=self.probabilities.values())))
def open(self):
return f'You loot {self.item}'
loot = container().open()
print(loot)
Error:
Traceback (most recent call last):
File "mtrand.pyx", line 1115, in mtrand.RandomState.choice
TypeError: 'dict_keys' object cannot be interpreted as an integer
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 14, in <module>
loot = container().open()
File "test.py", line 8, in __init__
self.item = choice(self.inv(choice(self.probabilities.keys(), p=self.probabilities.values())))
File "mtrand.pyx", line 1117, in mtrand.RandomState.choice
ValueError: 'a' must be 1-dimensional or an integer
As per the documentation of np.random.choice it takes in a 1D array or int a
and a probability vector p
whose length is equal to length of a
and sums to one. In your case you are feeding probabilities.keys()
and inv.keys()
which are of type dict_keys
. Also, your probability vector doesn’t sum to 1. one way to convert the probability vector to the required format is to divide it by the sum of it. I have make the necessary changes to the code
from numpy.random import choice
class container:
def __init__(self):
self.inv = {'common': ['blunt sword', 'blunt axe'], 'uncommon': ['Dynasty bow', 'Axe', 'Sword'], 'rare': ['Sharp axe'], 'epic': ['Great Sword']}
self.probabilities = {"common": 50, 'uncommon':25, 'rare': 10, 'epic': 3}
self.convert_prob_vector()
self.item = choice(self.inv[choice(list(self.probabilities.keys()), p=self.probabilities_new)])
def convert_prob_vector(self):
self.probabilities_new = [x / sum(self.probabilities.values()) for x in self.probabilities.values()]
def open(self):
return f'You loot {self.item}'
loot = container().open()
print(loot)
Sample Output
You loot Dynasty bow