从列表动态创建变量和数据帧
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]
我知道接下来的事情应该是:
从列表 prod_cols 创建变量名称并存储
列表中的那些变量 - 让我们将列表命名为 prod_dfs
prod_dfs = []
正在创建创建数据框并追加的动态公式
使用下面的“逻辑”将它们的变量名称更改为 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 是列数。
你可以用稍微不同的逻辑得到你想要的结果。
- 形成每个客户群的小组。
- 对于每个产品,计算购买者的数量
- 合并结果
这一行实现了这一逻辑。
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
更容易,因为它允许您更有效地使用其他编程结构。
我正在尝试为我的销售 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]
我知道接下来的事情应该是:
从列表 prod_cols 创建变量名称并存储 列表中的那些变量 - 让我们将列表命名为 prod_dfs
prod_dfs = []
正在创建创建数据框并追加的动态公式 使用下面的“逻辑”将它们的变量名称更改为 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 是列数。
你可以用稍微不同的逻辑得到你想要的结果。
- 形成每个客户群的小组。
- 对于每个产品,计算购买者的数量
- 合并结果
这一行实现了这一逻辑。
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
更容易,因为它允许您更有效地使用其他编程结构。