Reputation: 11
Data:
Items Category Value
apple Fruits 2
banana Fruits 2
grapes Fruits 4
Abhi Names 5
Ayush Names 4
Krish Names 3
Kartik Names 4
Paras Names 3
School Place 5
Playground Place 4
Courtyard Place 1
Farm Place 4
Shirt Clothes 6
Pant Clothes 4
Jeans Clothes 1
Socks Clothes 2
Shoes Clothes 1
Handkerchief Clothes 1
Jacket Clothes 3
T-Shirt Clothes 4
Code:
import pandas as pd
from itertools import permutations, combinations
Grouped = data.groupby(["Category"])
Fruits = Grouped.get_group('Fruits')
Names = Grouped.get_group('Names')
Place = Grouped.get_group('Place')
Clothes = Grouped.get_group('Clothes')
all = combinations([Fruits, Names, Place, Clothes], 6)
for i in all:
print (i)
I want only 6 items from the possible combinations of all categories (Fruits
, Names
, Place
and Clothes
) and the total value of those 6 items mustn't exceed 15.
Also, the combination must contain:
Items Minimum & Maximum
Fruits = 1->3
Names = 2->3
Place = 1->2
Clothes = 2->4
Upvotes: 0
Views: 136
Reputation: 1888
This is a perfect fit for itertools
. We'll use combinations() to generate all possible combinations of desired length, and then use filterfalse() to select those
that satisfy the conditions.
Using the data from the question, we find 32 combinations that satisfy the conditions out of 38,760 possible combinations.
One complication, and probably the reason that the partial program in the question does not print any combinations, is that a pandas
dataframe does not iterate in a straight-forward manner, since a dataframe is really structured object. The solution below uses df.values
to get a numpy
array of items (each being a list length 3) as input to combinations().
The sample data set from the question can be used as a string input:
datastr = """
Items Category Value
apple Fruits 2
banana Fruits 2
grapes Fruits 4
Abhi Names 5
Ayush Names 4
Krish Names 3
Kartik Names 4
Paras Names 3
School Place 5
Playground Place 4
Courtyard Place 1
Farm Place 4
Shirt Clothes 6
Pant Clothes 4
Jeans Clothes 1
Socks Clothes 2
Shoes Clothes 1
Handkerchief Clothes 1
Jacket Clothes 3
T-Shirt Clothes 4
"""
Using StringIO
to load the sample data set as a string:
from io import StringIO
import itertools
import pandas as pd
df = pd.read_table(StringIO(datastr), sep='\s+')
def is_not_valid(t):
""" t is not a valid tuple if sum > 15 or min/max exceeded """
t_sum = 0
if t_sum > 15:
return True
for item in t:
t_sum += item[2]
if t_sum > 15:
return True
if item[1] == 'Fruits' and not 1 <= item[2] <= 3:
return True
if item[1] == 'Names' and not 2 <= item[2] <= 3:
return True
if item[1] == 'Place' and not 1 <= item[2] <= 2:
return True
if item[1] == 'Clothes' and not 2 <= item[2] <= 4:
return True
return False
all = itertools.combinations(df.values, 6)
for t in itertools.filterfalse(is_not_valid, all):
print('(', end='')
for j,n in enumerate(t):
print(n[0], end='')
if j < 6-1:
print(', ', end='')
print(')')
Start and finish of the output:
(apple, banana, Krish, Paras, Courtyard, Pant)
(apple, banana, Krish, Paras, Courtyard, Socks)
# ...
(banana, Paras, Courtyard, Pant, Socks, Jacket)
(banana, Paras, Courtyard, Socks, Jacket, T-Shirt)
Upvotes: 1