0

I'm tring to create a dictionary importing data from an excel file converted in csv and I want to convert the string value of the dictionary into float, but I get in return this error ValueError: invalid literal for float(): 437,33

import csv
from collections import defaultdict

my_dict = {}
my_dict = defaultdict(lambda : 0, my_dict)

with open('excel_csv_file.csv', 'rb') as file_object:
    reader = csv.reader(file_object, delimiter=';')
    for x in reader:
        my_dict[(x[0], x[1])] = x[2]

my_dict = dict((k, float(v)) for k,v in my_dict.iteritems())
print my_dict

This is what my_dict looks like

{('11605', 'TV'): '437,33',
 ('10850', 'SMARTPHONE'): '163,47',
 ('11380', 'TV'): '1911,72',
 ('11177', 'SMARTPHONE'): '255,80',
 ('11237', 'TABLET'): '382,28',
 ('11238', 'TABLET'): '458,01',
 ('11325', 'TABLET'): '309,55',
 ...}

Why am I getting this error?

Also, is there a way to convert the string value inside the tuple key into an int? (for instance ('11605', 'TV') to (11605, 'TV'))?

1
  • Sounds like your data comes from somewhere where people use , to separate the integer and fraction parts of a number. Python expects . for that. Commented May 19, 2017 at 20:24

4 Answers 4

1

Python uses . (period) to separate the integer and fraction parts of a floating-point number, but your data uses , (comma).

To convert to int, you can use value unpacking:

line my_dict = dict(((int(k1), k2), float(v.replace(',', '.'))) for (k1,k2),v in my_dict.iteritems())

Since you’re using Python 2.7, you can also use a dict comprehension to make this simpler:

line my_dict = {(int(k1), k2): float(v.replace(',', '.')) for (k1,k2),v in my_dict.iteritems()}

Bonus:

If you have input from countries other than the US, and you expect you might run into other issues similar to your decimal separation one, you can use the locale module. If you start the script with

import locale
locale.setlocale(locale.LC_ALL, '')

you can use the various functions in the locale module locale.atof) instead of the built-in conversion methods like float, and it will automatically handle the user’s locale settings.

Sign up to request clarification or add additional context in comments.

5 Comments

I’ve added mention of the locale module. For simple scripts it’s often overkill, but if you live outside the US or expect a lot of people to use your code, it can be useful.
Somebody downvoted this, and I don’t know why. If there’s a problem with it, could you please explain?
Using your code I get the same error and I think that now it's because of the period used to separate thousands instead of the comma ValueError: invalid literal for float(): 2.688.44
The sample data you gave doesn’t have thousands separators. If your actual data does, then you’ll need to handle that somehow. It looks like locale.atof supports digit grouping, or you can just .replace it with the empty string, at the cost of breaking if any of the input uses . as a decimal separator.
Thank you, I resolved using locale.atof ! I don't know why someone downvoted your answer, it's just great!
1
>>> float('382,28')
ValueError: invalid literal for float(): 382,28

Because Python expects . for separating the integer and fraction parts of a number. The easiest thing you can do is to replace it:

>>> float('382,28'.replace(",", "."))
382.28

--

my_dict = dict((k, float(v.replace(",", "."))) for k, v in my_dict.iteritems())

Comments

1

For the first error, you must change your floats Strings data that looks like, for example "22,32" to "22.32", replace the , for . . For the second question, if you want to get an int from a string, just do int("43") for example.

Comments

0

Daniel H already said that in his Bonus answer, but for short I would put the following instruction:

Set locale to spanish, and use locale.atof instead of float.

In code it would be:

import locale
locale.setlocale(locale.LC_NUMERIC,"es_ES")
locale.atof("123,45")

in your case, use

my_dict = dict((k, locale.atof(v)) for k,v in my_dict.iteritems())

instead of

my_dict = dict((k, float(v)) for k,v in my_dict.iteritems())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.