【问题标题】:Appending item from a list to a Pandas df with rules将列表中的项目附加到带有规则的 Pandas df
【发布时间】:2021-09-22 18:35:10
【问题描述】:

我正在创建一个随机膳食生成器。这个想法是它从字典中随机选择餐点,并应用一周中的哪一天来吃那顿饭。它只会挑选一周的食物,因此只会选择 7 种食谱。到目前为止,这是我的代码:

meals = {'Recipe': ['Chicken Kebab', 'Chicken Balti', 'Chicken Stir Fry', 'Chicken Curry', 'Cola Chicken', 'Chicken Fajita Pie',
                    'Chicken in Black Bean Sauce', 'Stuffed Meatballs', 'Pesto Pasta'],
         'Book': ['1', '1', '1', '1', '1', '1', '1', '1', '1'],
         'Page': ['48', '50', '52', '58', '72', '74', '80', '87', '108'],
         'Category': ['Normal', 'Curry', 'Asian', 'Curry', 'Normal', 'Normal', 'Asian', 'Pasta', 'Pasta'],
         'Vegetarian': ['No', 'No', 'No', 'No', 'No', 'No', 'No', 'No', 'Yes']}


df = pd.DataFrame(meals)

days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

print (df)
mealdays = []
while len(meals['Recipe']) != len(days):
    days.append(" ")
while len(meals['Recipe']) != len(mealdays):
    day = random.choice(days)
    mealdays.append(day)
    days.remove(day)


random.shuffle(days)

df['Days'] = mealdays
print (df)

这非常适合随机选择餐点,但我现在要做的是引入一些规则,以便不会多次选择某些“类别”。例如,如果已为“星期一”随机选择了“咖喱”类别食谱,那么我不希望在本周剩下的时间里使用另一个“咖喱”类别食谱。我假设这将是第二个 While 循环中的 If 语句,但我不确定它会是什么。

【问题讨论】:

  • 如果meals 是字典列表而不是列表字典,事情会容易得多。
  • 但是你只有4个分类,有7天。
  • 当您选择食谱时,将其类别放入列表中。然后在选择下一个食谱时,循环直到你得到一个不在同一类别中的食谱。
  • 这与有多少类别无关,数据框中有超过 7 行,我希望星期几成为一个新列,其中包含星期几,其他人将保持空白

标签: python pandas list dictionary while-loop


【解决方案1】:

我已修改您的数据,使您至少有 7 个类别,否则将无法添加您的约束。在任何情况下,您都可以按类别分组并从每个类别中抽取 1 个样本,然后从其中随机抽取 7 个样本,并将日期映射到它们。

meals = {'Recipe': ['Chicken Kebab', 'Chicken Balti', 'Chicken Stir Fry', 'Chicken Curry', 'Cola Chicken', 'Chicken Fajita Pie',
                    'Chicken in Black Bean Sauce', 'Stuffed Meatballs', 'Pesto Pasta'],
         'Book': ['1', '1', '1', '1', '1', '1', '1', '1', '1'],
         'Page': ['48', '50', '52', '58', '72', '74', '80', '87', '108'],
         'Category': ['Normal', 'Curry', 'Asian', 'Curry', 'American', 'Diet', 'Asian', 'Pasta', 'Frozen'],
         'Vegetarian': ['No', 'No', 'No', 'No', 'No', 'No', 'No', 'No', 'Yes']}


df = pd.DataFrame(meals)

days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']


df.loc[df.groupby('Category').sample(1).sample(7).index, 'Days'] = days
df.fillna('', inplace=True)

输出

                      Recipe Book Page  Category Vegetarian Days
0                Chicken Kebab    1   48    Normal         No  Sun
1                Chicken Balti    1   50     Curry         No     
2             Chicken Stir Fry    1   52     Asian         No     
3                Chicken Curry    1   58     Curry         No  Fri
4                 Cola Chicken    1   72  American         No  Tue
5           Chicken Fajita Pie    1   74      Diet         No  Sat
6  Chicken in Black Bean Sauce    1   80     Asian         No  Wed
7            Stuffed Meatballs    1   87     Pasta         No  Mon
8                  Pesto Pasta    1  108    Frozen        Yes  Thu

【讨论】:

  • 我不是在为一周中的每一天寻找不同的类别,只有某些类别我不想被选中两次,例如我不想 2 咖喱一周内的食谱,我不希望一周内有 2 个意大利面食谱,其余的可以在一周内吃多次
【解决方案2】:

IIUC 使用 sample 随机播放您的 df,然后查找并删除重复的咖喱和意大利面:

cat = ["Curry", "Pasta"]

df = df.sample(frac=1)
s = df[df["Category"].isin(cat)].drop_duplicates("Category", keep="last").index
print (df[~df.index.isin(s)])

                        Recipe Book Page Category Vegetarian
6  Chicken in Black Bean Sauce    1   80    Asian         No
4                 Cola Chicken    1   72   Normal         No
2             Chicken Stir Fry    1   52    Asian         No
1                Chicken Balti    1   50    Curry         No
8                  Pesto Pasta    1  108    Pasta        Yes
0                Chicken Kebab    1   48   Normal         No
5           Chicken Fajita Pie    1   74   Normal         No

【讨论】:

    【解决方案3】:

    我想出了这个。它有效,因为一周没有那么多天。但是Henry's answer 看起来效率更高。

    certain_categories = ['Curry']
    
    pool = df
    picked = []
    for day in days:
        meal = pool.sample(1)
        df.loc[meal.index, 'Days'] = day
        if meal['Category'].item() in certain_categories:
            picked.append(meal['Category'].item())
        pool = df[df['Days'].isnull() & ~df['Category'].isin(picked)]
    df.fillna('', inplace=True)
        
    print(df)
                            Recipe Book Page Category Vegetarian Days
    0                Chicken Kebab    1   48   Normal         No     
    1                Chicken Balti    1   50    Curry         No     
    2             Chicken Stir Fry    1   52    Asian         No  Sun
    3                Chicken Curry    1   58    Curry         No  Thu
    4                 Cola Chicken    1   72   Normal         No  Tue
    5           Chicken Fajita Pie    1   74   Normal         No  Fri
    6  Chicken in Black Bean Sauce    1   80    Asian         No  Wed
    7            Stuffed Meatballs    1   87    Pasta         No  Mon
    8                  Pesto Pasta    1  108    Pasta        Yes  Sat
    
    

    【讨论】:

      猜你喜欢
      • 2020-09-29
      • 2017-06-05
      • 1970-01-01
      • 2019-06-11
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      • 2014-12-29
      相关资源
      最近更新 更多