1

I have a dictionary called purchases that has the payment method as the key and a dictionary containing payment types and their frequency as the values. Example formatting is as follows:

{'Credit card': {'Grocery': 3, 'Gas': 1, 'Store': 2},
'Debit card': {'Food': 2},
'Check': {'Rent': 1, 'Utilities': 1}, … }

I want to create a new dictionary with the frequency of payment methods as the key and the payment method as the values. Desired output:

[{6: ['Credit card']}, {2: ['Debit card', 'Check']}]

Here's my code so far:

artist_count = {}
for artist in artist_songs.keys():
    if artist in artist_count:
        artist_count[artist] += 1
    else:
        artist_count[artist] = 1
print(artist_count)

Currently, this outputs a dictionary with each unique payment method as a key and 1 as its value. I am having difficulty calculating the frequency of each, as well as switching the keys and the values. (I believe I can use the len function for the former, but I have not had luck with that yet.)

How can I create a new dictionary with the frequency of payment methods as the key and the payment method as the values?

  • Please pose a real question instead. Thanks in advance. – Peter Mortensen Nov 27 '19 at 01:18
  • @PeterMortensen just edited it. – markellefultz20 Nov 27 '19 at 01:21
  • You will have to first count the frequency of the payment methods. Once you have that you can loop over the values and populate a new dictionary where if a frequency exists you add the payment to its list, otherwise you add a new item to the dict with a new frequency and a list with a single payment method. Hope this helps. – k88 Nov 27 '19 at 01:31
  • 1
    Do you really want the frequency of payment methods as the key? I'm not seeing a good use case for that. Wouldn't you rather have the payment method remain as the key, but have a new dict with key=payment method, and value=frequency? – topher217 Nov 27 '19 at 01:37
  • 1
    Did you want a list or dict as the desired output? You wrote dict, but your example was a list. I edited your question assuming it to be a dict as the desired output, but you could equally well edit the text of the question to require a list as the output. – topher217 Nov 27 '19 at 03:34
  • Agreed with @topher217, this is somewhat ambiguous and possibly a poor design choice. – AMC Nov 27 '19 at 05:42

6 Answers6

3

Let us do this in two steps:

  1. We first make a dictionary where the key is payment type and value is the frequency.
  2. Then, we reverse this dictionary to obtain the dictionary that you want.

For the first part,

freq_dict = {}
for key in given_dict:
    freq_dict[key] = 0
    for item in given_dict[key]:
        freq_dict[key]+=given_dict[key][item]

For the second part:

result_dict = {}
for key in freq_dict:
    value = freq_dict[key]
    if value not in result_dict:
        result_dict[value] = []
    result_dict[value].append(key) 

given_dict is the dictionary that we start with.

Let me know if something is not clear :)

Shagun Sodhani
  • 3,535
  • 4
  • 30
  • 41
2

My solution follows the same logic as @Shagun Sodhani but uses one loop instead of two

payments = {'Credit card': {'Grocery': 3, 'Gas': 1, 'Store': 2},
'Debit card': {'Food': 2},
'Check': {'Rent': 1, 'Utilities': 1}}

sums = {}

for payment_type, payment_entries in payments.items():
    # calculate the number of times that a payment was used
    payment_type_frequency = sum(payment_entries.values())

    # check if the frequencu is already in the result array
    if payment_type_frequency in sums.keys():
        # if yes, append
        sums[payment_type_frequency].append(payment_type)
    else:
        # else add a new key and assign a one element list to it
        sums[payment_type_frequency] = [payment_type]

print(sums)

We can also simplify this code using a defaultdict:

import collections 

payments = {'Credit card': {'Grocery': 3, 'Gas': 1, 'Store': 2},
'Debit card': {'Food': 2},
'Check': {'Rent': 1, 'Utilities': 1}}

sums = collections.defaultdict(list)

for payment_type, payment_entries in payments.items():
    # calculate the number of times that a payment was used
    payment_type_frequency = sum(payment_entries.values())
    # check if the frequency is already in the result array
    sums[payment_type_frequency].append(payment_type)

print(sums)

or we can also use a list comprehension to have a smarter-looking, but unreadable code (not suggested in any production code):

import collections 

payments = {'Credit card': {'Grocery': 3, 'Gas': 1, 'Store': 2},
'Debit card': {'Food': 2},
'Check': {'Rent': 1, 'Utilities': 1}}

sums = collections.defaultdict(list)

[sums[sum(payment_entries.values())].append(payment_type) for payment_type, payment_entries in payments.items()]

print(sums)
Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
2
purchases = {'Credit card': {'Grocery': 3, 'Gas': 1, 'Store': 2},
'Debit card': {'Food': 2}, 'Check': {'Rent': 1, 'Utilities': 1}}

paymentFreq = {}

for method, category in purchases.items():
    countSum = 0
    for item, count in category.items():
        countSum = countSum + count
    if countSum not in paymentFreq:
        paymentFreq[countSum] = [method]
    else:
        paymentFreq[countSum].append(method)

print(paymentFreq)
topher217
  • 1,188
  • 12
  • 35
2

can also do it in pandas this way:

df = pd.DataFrame({'vals':[*in_dict.values()],'vars':[*in_dict.keys()]})
df['vals'] = df['vals'].apply(lambda x: sum(x.values())) #because nested dict
out_dict = df.groupby('vals')['vars'].agg(list).to_dict()

output:

{2: ['Debit card', 'Check'], 6: ['Credit card']}
Derek Eden
  • 4,403
  • 3
  • 18
  • 31
2

An easy way would be to use a collections.defaultdict of lists here to group by sums and append the payment methods:

from collections import defaultdict

data = {
    "Credit card": {"Grocery": 3, "Gas": 1, "Store": 2},
    "Debit card": {"Food": 2},
    "Check": {"Rent": 1, "Utilities": 1},
}

payment_map = defaultdict(list)
for method, payments in data.items():
    total = sum(payments.values())
    payment_map[total].append(method)

print([{k: v} for k, v in payment_map.items()])
# [{6: ['Credit card']}, {2: ['Debit card', 'Check']}]

The benefit of using a defaultdict here is because it automatically creates the list for you when a new key is added. You don't have to do it yourself, which also leads to cleaner code.

If you prefer a non-library solution, you can use dict.setdefault() here instead:

payment_map = {}
for method, payments in data.items():
    total = sum(payments.values())
    payment_map.setdefault(total, []).append(method)

Note: How does collections.defaultdict work? is a good question to explore for more information about how defaultdict works.

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
1

If pandas is an option, Try this:

import pandas as pd
import collections

mycounter=[]
dff = {'Credit card': {'Grocery': 3, 'Gas': 1, 'Store': 2},'Debit card': {'Food': 2},'Check': {'Rent': 1, 'Utilities': 1}}

newdf2 = pd.read_json(json.dumps(dff))
for i,j in newdf2.iteritems():
    mycounter.append({ newdf2[i].sum().astype(int) :[i]})

res = {}
for d in mycounter:
    for k, v in d.items():
        res.setdefault(k, []).extend(v)

res
#[{6: ['Credit card']}, {2: ['Debit card', 'Check']}]


oppressionslayer
  • 6,942
  • 2
  • 7
  • 24