1

I have a csv file that has numbers integers and floats,

"5",7.30124705657363,2,12,7.45176205440562
"18",6.83169608190656,5,11,7.18118108407457
"20",6.40446470770985,4,10,6.70549470337383
"3",5.37498781178147,17,9,5.9902122724706
"10",5.12954203598201,8,8,5.58108702947798
"9",3.93496153596789,7,7,4.35751055597501

I am doing some arithmetic and then I am trying to add them into a dictionary but I am getting key error. Here is the code that I have,

global oldPriceCompRankDict
oldPriceCompRankDict = {}

def increaseQuantityByOne(self, fileLocation):
    rows = csv.reader(open(fileLocation))
    rows.next()
    print "PricePercentage\t" + "OldQuantity\t" + "newQuantity\t" + "oldCompScore\t" + "newCompScore"
    for row in rows:
        newQuantity = float(row[2]) + 1.0
        newCompetitiveScore = float(row[1]) + float(math.log(float(newQuantity), 100))
        print row[1] + "\t", str(row[2])+"\t", str(newQuantity) + "\t", str(row[4]) + "\t", newCompetitiveScore
        oldPriceCompRankDict[row[3]].append(row[4])

I have un-ordered key, and I didn't think the key has to be in an ordered format. I thought anything could be key.

add-semi-colons
  • 18,094
  • 55
  • 145
  • 232
  • 3
    When you get a Python traceback, please share it so people answering do not have to go hunting in your code where the error may have been coming from. – Martijn Pieters Jun 18 '12 at 17:13

2 Answers2

4

No need to put in the global keyword, it's a no-op. Use a defaultdict instead:

from collections import defaultdict

oldPriceCompRankDict = defaultdict(list)

What is happening is that you never define any keys for oldPriceCompRankDict, you just expect them to be lists by default. The defaultdict type gives you a dict that does just that; when a key is not yet found in oldPriceCompRankDict a new list() instance will be used as the starting value instead of raising a KeyError.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I also resolved the issue by oldPriceCompRankDict[row[3]] = row[4] is this a good practice? – add-semi-colons Jun 18 '12 at 17:28
  • 1
    @Null-Hypothesis: In that case at least you are assigning a new key/value to your dict, yes. If that's what you want instead of having a dict of lists, that's just fine. :-) – Martijn Pieters Jun 18 '12 at 17:30
  • @Null-Hypothesis: Let's not use SO comments as a support forum; better search SO for possible answers and/or create a new question (after you tried some things). – Martijn Pieters Jun 18 '12 at 17:41
2

A Python dictionary type does not have an append() method. What you are doing is basically trying to call an append() method of the dictionary element accessible by key row[3]. You get a KeyError because you have nothing under key row[3].

You should substitute your code

oldPriceCompRankDict[row[3]].append(row[4])

for this:

oldPriceCompRankDict[row[3]] = row[4]

In addition, the global keyword is used inside functions to indicate that variable is a global one, you can read about it here: Using global variables in a function other than the one that created them so the right way to declare a global dictionary would be just oldPriceCompRankDict = {}

Your function will start adding to the dictionary from the second row because you call rows.next() if it is a desirable behavior then it's OK, otherwise you don't need to call that method.

Hope this was helpful, happy coding!

Community
  • 1
  • 1
Alexander Nyrkov
  • 445
  • 1
  • 5
  • 12