从列表动态创建变量和数据帧

Dynamically Creating Variables and DataFrames from A List

我正在尝试为我的销售 table 中的每个不同产品创建独特买家的摘要。我的目标结果如下:

CustSeg UNIQUE_PROD1_CUST
0 7
1 8
2 4

创建此摘要并将其分配给如下变量:

# Count of DISTINCT PROD1 CUSTOMERS

PROD1_CUST = (
    Sales_Df.loc[(Sales_Df.Prod1_Qty > 0)]
    .groupby("CustSeg")["CustID"]
    .count()
    .reset_index(name="UNIQUE_PROD1_CUST")
)

PROD1_CUST

Sales_Df数据框可以这样复制:

Sales_Qty = {
    "CustID": ['C01',   'C02',  'C03',  'C04',  'C05',  'C06',  'C07',  'C08',  'C09',  'C10',  'C11',  'C12',  'C13',  'C14',  'C15',  'C16',  'C17',  'C18',  'C19',  'C20', ],
    "CustSeg": ['High',     'High',     'Mid',  'High',     'Low',  'Low',  'Low',  'Low',  'Low',  'Mid',  'Low',  'Low',  'Mid',  'Low',  'High',     'High',     'High',     'High',     'Mid',  'Low',  ],
    "Prod1_Qty": [8,    7,  12,     15,     7,  15,     7,  8,  3,  15,     0,  3,  4,  4,  7,  11,     12,     12,     6,  1, ],
    "Prod2_Qty": [2,    5,  0,  1,  14,     15,     3,  1,  11,     0,  5,  11,     12,     8,  6,  15,     7,  4,  3,  10, ],
    "Prod3_Qty": [13,   4,  0,  11,     3,  5,  11,     11,     10,     14,     2,  4,  3,  14,     14,     10,     5,  0,  0,  9,  ],
    "Prod4_Qty": [11,   15,     2,  0,  6,  2,  12,     14,     11,     15,     5,  14,     13,     0,  10,     2,  13,     11,     12,     15, ],
    "Prod5_Qty": [9,    15,     5,  4,  9,  0,  13,     9,  8,  11,     10,     12,     8,  3,  14,     11,     9,  15,     8,  14, ]
}
Sales_Df = pd.DataFrame(Sales_Qty)
Sales_Df

现在,在现实生活中,数据框的形状要大得多(至少 (5000000, 130)),这使得手动重复每个产品的摘要变得脆弱,所以我正在尝试自动创建变量和摘要。我正在通过以下步骤完成任务。

# Extract the proposed variable names from the dataframe column names.
all_cols = Sales_Df.columns.values.tolist()

# Remove non-product quantity columns from the list
not_prod_cols = ["CustSeg", "CustID"]
prod_cols = [x for x in all_cols if x not in not_prod_cols]

我知道接下来的事情应该是:

  1. 从列表 prod_cols 创建变量名称并存储 列表中的那些变量 - 让我们将列表命名为 prod_dfs

    prod_dfs = []
    
  2. 正在创建创建数据框并追加的动态公式 使用下面的“逻辑”将它们的变量名称更改为 prod_dfs

    for x in prod_cols:
         x[:-4] + "_CUST" = (
            Sales_Df.loc[(Sales_Df.x > 0)]
            .groupby("CustSeg")["CustID"]
            .count()
            .reset_index(name="UNIQUE" + x[:-4] + "_CUST")
        )
    
prod_dfs.append(x)

这就是我卡住的地方。请协助。

感谢您分享可重现的示例,看来您已经取得了不错的进步。如果我理解正确,您希望能够计算每个细分市场中购买了给定商品的唯一客户数量。

要遵循您的方法,您可以遍历产品列,计算计数,并将其分配给结果数据框:

prod_cols = [col for col in Sales_Df.columns if col.startswith('Prod')]
result = None
for prod in prod_cols:
    counts = (
        Sales_Df
        .loc[Sales_Df[prod] > 0]
        .groupby('CustSeg')
        [prod]
        .count()
    )
    if result is None:
        result = counts.to_frame()
    else:
        result[prod] = counts
CustSeg Prod1_Qty Prod2_Qty Prod3_Qty Prod4_Qty Prod5_Qty
High 7 7 6 6 7
Low 8 9 9 8 8
Mid 4 2 2 4 4

这将在第二个维度上对您有所帮助,因为您不必为所有列编写此聚合代码。

但是,生成的代码不是很有效,因为它执行 O(m) groupby 操作,其中 m 是列数。

你可以用稍微不同的逻辑得到你想要的结果。

  1. 形成每个客户群的小组。
  2. 对于每个产品,计算购买者的数量
  3. 合并结果

这一行实现了这一逻辑。

Sales_Df.drop('CustID', axis=1).groupby('CustSeg').apply(lambda group: (group>0).sum(axis=0))

请注意,我们首先删除 CustID,因为在您的示例中,按 CustSeg 分组后,它是唯一不是产品数量的列。

顺便说一句:考虑查看 pandas indexing basics。您可能会发现使用 df['A'] 的语法比 df.A 更容易,因为它允许您更有效地使用其他编程结构。