bwrr
bwrr

Reputation: 621

Unable to append a list of values to specific keys of a dictionary

1) I first map the key names to a dictionary called main_dict with an empty list (the actual problem has many keys hence the reason why I am doing this)

2) I then loop over a data matrix consisting of 3 columns

3) When I append a value to a column (the key) in the dictionary, the data is appended to wrong keys.

Where am I going wrong here?

Minimum working example: Edit: The data is being read from a file row by row and does not exist in lists as in this MWE. Edit2: Prefer a more pythonic solution than Pandas.

import numpy as np
key_names = ["A", "B", "C"]
main_dict = {}
val = []
main_dict = main_dict.fromkeys(key_names, val)

data = np.array([[2018, 1.1, 3.3], [2017, 2.1, 5.4], [2016, 3.1, 1.4]])

for i in data:
    main_dict["A"].append(i[0])
    main_dict["B"].append(i[1])
    main_dict["C"].append(i[2])

print(main_dict["A"])

# Actual output: [2018.0, 1.1, 3.3, 2017.0, 2.1, 5.4, 2016.0, 3.1, 1.4]

# print(main_dict["A"])
# Expected output: [2018.0, 2017.0, 2016.0]
# print(main_dict["B"])
# Expected output: [1.1, 2.1, 3.1]
# print(main_dict["C"])
# Expected output: [3.3, 5.4, 1.4]

Upvotes: 1

Views: 165

Answers (2)

Saurabh Sangwan
Saurabh Sangwan

Reputation: 427

The problem is in

main_dict = main_dict.fromkeys(key_names, val)

The same list val is referenced by all the keys since python passes reference.

Upvotes: 0

Without using numpy (which is a heavy weight package for what you are doing) I would do this:

keys = ["A", "B", "C"]
main_dict = {key: [] for key in keys}

data = [[2018, 1.1, 3.3], [2017, 2.1, 5.4], [2016, 3.1, 1.4]]

# since you are reading from a file
for datum in data:
    for index, key in enumerate(keys):
        main_dict[key].append(datum[index])

print(main_dict) # {'A': [2018, 2017, 2016], 'B': [1.1, 2.1, 3.1], 'C': [3.3, 5.4, 1.4]}

Alternatively you can use the built-in defaultdict which is a tad faster since you don't need to do the dictionary comprehension:

from collections import defaultdict
main_dict = defaultdict(list)

keys = ["A", "B", "C"]
data = [[2018, 1.1, 3.3], [2017, 2.1, 5.4], [2016, 3.1, 1.4]]

# since you are reading from a file
for datum in data:
    for index, key in enumerate(keys):
        main_dict[key].append(datum[index])

print(main_dict)

Lastly, if the keys really don't matter to you, you can be a little more dynamic by coming up with the keys dynamically starting from A. Thus allowing lines to have more than three attributes:

from collections import defaultdict
main_dict = defaultdict(list)

data = [[2018, 1.1, 3.3], [2017, 2.1, 5.4], [2016, 3.1, 1.4]]

# since you are reading from a file
for datum in data:
    for index, attr in enumerate(datum):
        main_dict[chr(ord('A') + index)].append(attr)

print(main_dict) # {'A': [2018, 2017, 2016], 'B': [1.1, 2.1, 3.1], 'C': [3.3, 5.4, 1.4]}

Upvotes: 1

Related Questions