convert float values in dictionary into two decimal places - python

Note, using Python 2.4. Here is a dictionary I have called d_ourbook:
{'130405C00465000': [[8.6999999999999993, 8.9000000000000004, 0.50749999999999995, 32.810000000000002, -141.1575]]}
The value is a list of floats. I am trying to make a function that displays the same dictionary, but with values limited to two floating points.
I made a floating point --> 2decimal string function called two(floatnum):
def two(floatnum):
return '%.2f' %(floatnum)
My function to loop or zip through the dictionary and convert all the values to two(value) have been a nightmare and returns float argument required:
Traceback (most recent call last):
File "esecombo.py", line 496, in ?
print ' -- dt: ', dt(d_ourbook)
File "esecombo.py", line 23, in dt
new_d_name = dict(zip(d_name.keys(), [two(value)for value in d_name.values()]))
File "esecombo.py", line 10, in two
return '%.2f' %(floatnum)
TypeError: float argument required
Any help would be a lifesaver.

Assuming that d_name is the dictionary you provided, then d_name.values() is a list of lists of lists of floats. So value is a list of lists of floats and you cannot hand that to two() without an error.
Even if you get that resolved the zip returns a number of tuples base on the shortest argument.
So that:
new_d_name = dict(zip(d_name.keys(),
[two(value) for value in (d_name.values()[0][0])]))
results in {'130405C00465000': '8.70'}
This assumes that all values are of the single item list in list type as in the example, in that case you probably could use:
new_d_name = dict(zip(d_name.keys(),
[[two(value) for value in (d_name.values()[0][0])]]))
to get:
{'130405C00465000': ['8.70', '8.90', '0.51', '32.81', '-141.16']}

Related

How to get index position of values in python

I have a scenario , where I am trying to get index position of value
My code :
a_set = {22,56,26}
print(a_set[56])
Getting below error
Traceback (most recent call last):
File "<string>", line 5, in <module>
TypeError: 'set' object is not subscriptable
Expected output :
1 -> This the position of 56 from set
The error is explaining a lot here: sets in Python are not subscriptable.
They dont have order relation.
According to your code example, you are trying to ask weather a value exists in the set, right?
In Python you can do it with in operator:
>> print(36 in a_set)
True
or
if (36 in a_set):
my_function()
Sets are by definition completely unordered and unindexed, you cannot get the information with an index directly as that is not what they were made for. As a workaround, you can simply convert the set to a list that is both indexed and ordered.
a_set = {22,56,26}
print(list(a_set)[3]) # converts the set into and displays it's third entry.
To solve your problem, you can use .index() on the new list such as this:
a_set = {1,2,3}
print(list(a_set).index(1))

Is there a way to fix appending float values to dictionaries in Python?

I'm currently writing code that's supposed to read a file that has the dates and magnitudes of the major earthquakes in recent years and return a dictionary where the keys are the dates the earthquakes took place, and then the values are the magnitudes of the earthquakes that happened on that date.
My code currently looks like this:
def magnitudedictionary():
earth = open("earthquakes.txt", "r")
magdict = {}
for line in earth:
alist = line.split()
magnitude= float(alist[0])
date = alist[1]
if date in magdict:
magdict[date].append(magnitude)
else:
magdict[date] = magnitude
earth.close()
return magdict
But whenever I try to run the code, I always get a Traceback that says:
Traceback (most recent call last):
File "/Users/MargaretJagger/PycharmProjects/Homework 6/Q2.py", line 18, in <module> magnitudedictionary()
File "/Users/MargaretJagger/PycharmProjects/Homework 6/Q2.py", line 10, in magnitudedictionary
magdict[date].append(magnitude)
AttributeError: 'float' object has no attribute 'append'
Process finished with exit code 1
I'm not quite sure what the issue is exactly, but I know that it has something to do with the float and the dictionary values not matching up.
You probably want a defaultDict for this. Then you can avoid the test and just push into the values.
Here's a simple mockup:
from collections import defaultdict
earth = '''7.6 20190801
8.2 20180201
7.1 20190801
6.5 20190801
4.2 20180201'''
magdict = defaultdict(list) # values will default to new lists
for line in earth.split('\n'):
alist = line.split(' ')
magnitude= float(alist[0])
date = alist[1]
magdict[date].append(magnitude) #magdict[date] will default to a list if the key doesn't already exist
print(magdict['20190801'])
>>> [7.6, 7.1, 6.5]
the values are the magnitudes of the earthquakes that happened on that date.
Since you are talking of “magnitudes”, plural, I assume that you want to be able to store multiple values per date. That means that you should also make sure that your dictionary values are actual lists that store multiple values, instead of just a single value.
Compare the following example dictionaries:
{
"2019-04-17": 2.1,
"2019-04-18": 3.5
}
{
"2019-04-17": [1.7, 2.5],
"2019-04-18": [3.2]
}
The first dictionary only maps the date to a single float. So for every date key, you get a single value. The second dictionary maps to a list of floats. Such a list can only contain a single value, or many (it could also contain none).
When you look at your code that sets the values in the dictionary, you can see that you actually built this with multiple values in mind:
if date in magdict:
magdict[date].append(magnitude)
else:
magdict[date] = magnitude
When there’s already the date in the dictionary, then you want to append it. Otherwise you set the date/value pair directly (which adds the key). It’s just that the way you do it, you are setting a single float value (i.e. the first dictionary type above) instead of a list of floats.
So what you need to do instead is create a list of floats here:
if date in magdict:
magdict[date].append(magnitude)
else:
magdict[date] = [magnitude]
The [magnitude] create a one-element list with magnitude as the first value. Since the value in your dictionary is now a list, calls to append() will succeed and correctly add another value to the list.
The error is in the else clause.
It should be magdict[date] = [magnitude] and not magdict[date] = magnitude.
The python dictionary has a very nice method, setdefault, that should help here:
def magnitudedictionary():
earth = open("earthquakes.txt", "r")
magdict = {}
for line in earth:
alist = line.split()
magnitude= float(alist[0])
date = alist[1]
magdict.setdefault(date, []).append(magnitude)
earth.close()
return magdict
Here is a small bit of documentation on the method in question: https://www.tutorialspoint.com/python/dictionary_setdefault.htm

Reading in string of nested JSON lists and dictionaries with Python

I am having trouble reading data in python. A sample of one of the rows is:
foo_brackets='{"KEY2":[{"KEY2a":[{"KEY2a1":"4","KEY2a2":"5"},{"KEY2a1":"6","KEY2a2":"7"}],"KEY2b":"8"}],"KEY3":"9"}'
When I load with json, the value for KEY2 is read in as a list, because of the brackets, which then prevents me from getting at my desired result, which is the value of KEY2b:
>>> import json
>>> foo_brackets_json=json.loads(foo_brackets)
>>> foo_brackets_json['KEY2']['KEY2b']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not str
I could just try to remove the brackets, but there actually is a value that should be a list, KEY2a. You can see this if I strip out all the brackets and try to convert to JSON:
>>> foo_no_brackets='{"KEY2":{"KEY2a":{"KEY2a1":"4","KEY2a2":"5"},{"KEY2a1":"6","KEY2a2":"7"},"KEY2b":"8"},"KEY3":"9"}'
>>> json.loads(foo_no_brackets)
# Traceback omitted since it's just the python error
ValueError: Expecting property name: line 1 column 45 (char 45)
foo_brackets does appear to be valid JSON (I tested here, with the quotes removed) and got the following:
{
"KEY2":[
{
"KEY2a":[
{
"KEY2a1":"4",
"KEY2a2":"5"
},
{
"KEY2a1":"6",
"KEY2a2":"7"
}
],
"KEY2b":"8"
}
],
"KEY3":"9"
}
Question:
Is there a way for me to read objects like foo_brackets so that I can call foo_brackets_json['KEY2']['KEY2b']?
foo_brackets_json['KEY2'] references a list, here with one element.
You'll have to use integer indices to reference the dictionaries contained in that list:
foo_brackets_json['KEY2'][0]['KEY2b']
Don't try to remove the brackets; there could be 0 or more nested dictionaries here. You'll have to determine what should happen in those cases where you don't have just 1 nested dictionary.
The above hardcoded reference assumes there is always at least one such a dictionary in the list, and doesn't care if there are more than one.
You could use looping to handle the 0 or more case:
for nested in foo_brackets_json['KEY2']:
print(nested['KEY2b'])
Now you are handling each nested dictionary, one by one. This'll work for the empty list case, and if there is more than one.
You could make having 0 or more than one an error:
if len(foo_brackets_json['KEY2']) != 1:
raise ValueError('Unexpected number of results')
etc. etc. It all depends on your actual use-case.

How do I fix the RuntimeError in this program?

This program is a function that takes dictionary and it must return a new dictionary with mirror image of the original dictionary (meaning key:value pairs are switched).
However, according to pythontutor.com, for the line of code that says the for loop, it throws a RuntimeError.
I am using the latest version of Python (3.4.1)
#Program purpose: Write a function called rvBirthday that takes
# dictionary birthday as input. It returns a
# mirror image of the dictionary, where birthday
# is the key and name is the value.
def rvBirthday(birthday):
reverseBD = {}
for key in birthday.keys():
date = birthday.get(key)
birthday.pop(key)
reverseBD[date] = key
return reverseBD
birthday = {'Mitsuyuki Washida':'3-29-93', 'Joe Bob':'7-12-96',
'Sam Wilson':'4-1-02'}
print(rvBirthday(birthday))
The error I get is:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in rvBirthday
RuntimeError: dictionary changed size during iteration
You are altering the input dictionary while looping over it by using dict.pop(). This changes the dictionary size, and that breaks iteration.
Your instructions say nothing about removing keys from the input dictionary. Remove the dict.pop() calls altogether.
You don't need to use .keys() or .get() here either. Looping over a dictionary yields keys, so you don't have to use a separate method to extract the keys. You then know that those keys are in the dictionary, so .get() to return default if it is missing is also redundant.
Better loop over the dictionary items; this gives you both the key and the value in one step:
def rvBirthday(birthday):
reverseBD = {}
for key, date in birthday.items():
reverseBD[date] = key
return reverseBD
This can be expressed with a dictionary comprehension too:
def rvBirthday(birthday):
return {date: key for key, date in birthday.items()}
If you still need to clear the input dictionary, simply add a birthday.clear() call after copying across the key-value pairs.

strip ' from all members in a list

Ok, so I converted each line in a text file into a member of a list by doing the following: chkseq=[line.strip() for line in open("sequence.txt")] So when I print chkseq I get this: ['3','3'] What I would like is for it to instead look like this: [3,3] I know this is possible, I'm just unsure of how! I need them to be intergers, not strings. So if all else fails, that is my main goal in this: create a list from a .txt file whose members are intergers (which would be all the .txt file contained). Thanks!! -OSFTW
It looks like you want to interpret the strings as integers. Use int to do this:
chkseq = [int(line) for line in open("sequence.txt")]
It can also be written using map instead of a list comprehension:
chkseq = map(int, open("sequence.txt"))
iterate over the elements of your list and print them out with your preferred formatting rather than relying on the default formatting when printing the whole list at once.
Say your array is called input, and you want to store the value in an array called chkseq, your code would be:
chkseq = [int(i) for i in input]
Or, if you wanted to do everything all in one line:
chkseq = [int(i.strip()) for i in open("sequence.txt")]
Passing a string to the int constructor will attempt to turn it into a int.
>>> int('3')
3
>>> int('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'foo'

Categories