How to count multiple items in a list

Viewed 3019

I have the following list:

data = [[2004,1,1,1,50], [2008,2,28,1,150],[1984,5,1,3,20],[1982,5,1,7,20], [1982,5,8,7,20]]

The data represents the Year, Month, Day, Day of week, count.

I want to obtain a dictionary of the total counts per day of the week. Something like this

results = {1:200,
           2:0,
           3:20,
           4:0,
           5:0,
           6:0,
           7:40,
}

I believe the best way to do this, please correct me if i'm wrong, is to use collections.Counter. I abandoned this effort for a dictionary comprehension but have been unable to solve the problem

solution = {(x,i) for x[3], i[4] in data}
4 Answers

Since you want to sum and not count it might be easier to use defaultdict:

from collections import defaultdict

data = [[2004,1,1,1,50], [2008,2,30,1,150],[1984,5,1,3,20],[1982,5,1,7,20], [1982,5,8,7,20]]

c = defaultdict(int)

for l in data:
    c[l[3]] += l[4]

print(c)
# defaultdict(<class 'int'>, {1: 200, 3: 20, 7: 40})

If you insist on having zero entries you can instantiate it before:

from collections import defaultdict

data = [[2004,1,1,1,50], [2008,2,30,1,150],[1984,5,1,3,20],[1982,5,1,7,20], [1982,5,8,7,20]]

c = defaultdict(int)
c.update({d: 0 for d in range(1, 8)})
for l in data:
    c[l[3]] += l[4]
print(c)
# defaultdict(<class 'int'>, {1: 200, 2: 0, 3: 20, 4: 0, 5: 0, 6: 0, 7: 40})

At this point you may use a normal dict over defaultdict if you are sure that the input will not have invalid days:

data = [[2004,1,1,1,50], [2008,2,30,1,150],[1984,5,1,3,20],[1982,5,1,7,20], [1982,5,8,7,20]]

c = {d: 0 for d in range(1, 8)} # or dict.fromkeys(range(1, 8), 0)
for l in data:
    c[l[3]] += l[4]
print(c)
# {1: 200, 2: 0, 3: 20, 4: 0, 5: 0, 6: 0, 7: 40}

If, as in your input data, your data is sorted by day of week, i.e. all sublists for a particular day of week are adjacent to each other, you can use itertools.groupby with a dictionary comprehension:

from itertools import groupby
from operator import itemgetter

res = {k: sum(map(itemgetter(-1), v)) for k, v in groupby(data, key=itemgetter(-2))}

print(res)
# {1: 200, 3: 20, 7: 40}

If your data is not sorted, you will have to sort by day of week first:

data = sorted(data, key=itemgetter(-2))

You can tackle this problem with a simple loop instead. Create a results dict with initial values for each day set to zero, and just add to it step by step.

results = {k:0 for k in range(1,8)}
#Output: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0}
data = [[2004,1,1,1,50], [2008,2,30,1,150],[1984,5,1,3,20],[1982,5,1,7,20], [1982,5,8,7,20]]

for x in data:
    results[x[3]] += x[4]

print(results)
#Output:
{1: 200, 2: 0, 3: 20, 4: 0, 5: 0, 6: 0, 7: 40}

As you asked to use Counter from collections, you could use it like this:

from collections import Counter

counter=Counter()

for group in data:
    counter[group[3]] +=group[4]

results=dict(counter)
Related