按组和虚拟代码分类变量转换长格式分类数据
pivot long form categorical data by group and dummy code categorical variables
对于以下数据框,我试图将分类变量 ('purchase_item') 转换为宽格式并将它们虚拟编码为 1/0 - 基于客户是否在每个2016 年 4 个季度。
我想生成一个旋转数据框,如下所示:
为了获得上面显示的预期结果,我基本上尝试了各种方法来将 groupby/pivot_table 函数与对 pandas 中的 get_dummies() 函数的调用结合起来。例子:
data.groupby(["cust_id", "purchase_qtr"])["purchase_item"].reset_index().get_dummies()
但是,到目前为止,我的 none 次尝试都奏效了。
有人可以帮我生成想要的结果吗?
这样做的一种方法是获取交叉制表,然后强制所有 > 1 的值变为 1,同时保持所有 0 的原样:
TL;DR
out = (
pd.crosstab([df["cust_id"], df["purchase_qtr"]], df["purchase_item"])
.gt(0)
.astype(int)
.reset_index()
)
全部分解:
创建数据
df = pd.DataFrame({
"group1": np.repeat(["a", "b", "c"], 4),
"group2": [1, 2, 3] * 4,
"item": np.random.choice(["ab", "cd", "ef", "gh", "zx"], size=12)
})
print(df)
group1 group2 item
0 a 1 cd
1 a 2 ef
2 a 3 gh
3 a 1 ef
4 b 2 zx
5 b 3 ab
6 b 1 ab
7 b 2 gh
8 c 3 gh
9 c 1 cd
10 c 2 ef
11 c 3 gh
交叉表
这个 returns 频率 table 表示每个类别一起观察的频率:
crosstab = pd.crosstab([df["group1"], df["group2"]], df["item"])
print(crosstab)
item ab cd ef gh zx
group1 group2
a 1 0 1 1 0 0
2 0 0 1 0 0
3 0 0 0 1 0
b 1 1 0 0 0 0
2 0 0 0 1 1
3 1 0 0 0 0
c 1 0 1 0 0 0
2 0 0 1 0 0
3 0 0 0 2 0
将计数强制转换为虚拟代码
由于我们想要伪代码,而不是计算类别的共现,我们可以使用一个快速的技巧来强制所有大于 0 gt(0)
的值变为 1 astype(int)
item ab cd ef gh zx
group1 group2
a 1 0 1 1 0 0
2 0 0 1 0 0
3 0 0 0 1 0
b 1 1 0 0 0 0
2 0 0 0 1 1
3 1 0 0 0 0
c 1 0 1 0 0 0
2 0 0 1 0 0
3 0 0 0 1 0
您可以通过多种技巧在一行中完成。
1) 联结中的唯一索引计数与铸造为 bool
在任何情况下都有效,即使除了 index
、columns
和 values
之外没有任何其他列。此代码意味着计算每个索引列交集的唯一索引,并 returning 1
以防其超过 0
else 0
.
df.reset_index().pivot_table(index=['cust_id','purchase_qtr'],
columns='purchase_item',
values='index',
aggfunc='nunique', fill_value=0)\
.astype(bool).astype(int)
2) 检查是否有任何其他列不为空
如果您除了 index
、columns
和 values
之外还有其他列,并且想将它们用于直觉。就像你的 purchase_date
一样。它更直观,因为您可以像这样“阅读”它:如果商品的购买日期不为空,则每季度检查每个客户并将它们解析为整数。
df.pivot_table(index=['cust_id','purchase_qtr'],
columns='purchase_item',values='purchase_date',
aggfunc=lambda x: all(pd.notna(x)), fill_value=0)\
.astype(int)
3) 查看 len
个元素落入每个索引列交集
这会看到 len
个元素落在每个索引列交集中,并且 returning 1
以防超过 0
else 0
。同样直观的方法:
df.pivot_table(index=['cust_id','purchase_qtr'],
columns='purchase_item',
values='purchase_date',
aggfunc=len, fill_value=0)\
.astype(bool).astype(int)
所有 return 所需的数据帧:
请注意,当您还没有数据框时,您应该只使用 crosstab
,因为它会在内部调用 pivot_table
。
对于以下数据框,我试图将分类变量 ('purchase_item') 转换为宽格式并将它们虚拟编码为 1/0 - 基于客户是否在每个2016 年 4 个季度。
我想生成一个旋转数据框,如下所示:
为了获得上面显示的预期结果,我基本上尝试了各种方法来将 groupby/pivot_table 函数与对 pandas 中的 get_dummies() 函数的调用结合起来。例子:
data.groupby(["cust_id", "purchase_qtr"])["purchase_item"].reset_index().get_dummies()
但是,到目前为止,我的 none 次尝试都奏效了。
有人可以帮我生成想要的结果吗?
这样做的一种方法是获取交叉制表,然后强制所有 > 1 的值变为 1,同时保持所有 0 的原样:
TL;DR
out = (
pd.crosstab([df["cust_id"], df["purchase_qtr"]], df["purchase_item"])
.gt(0)
.astype(int)
.reset_index()
)
全部分解:
创建数据
df = pd.DataFrame({
"group1": np.repeat(["a", "b", "c"], 4),
"group2": [1, 2, 3] * 4,
"item": np.random.choice(["ab", "cd", "ef", "gh", "zx"], size=12)
})
print(df)
group1 group2 item
0 a 1 cd
1 a 2 ef
2 a 3 gh
3 a 1 ef
4 b 2 zx
5 b 3 ab
6 b 1 ab
7 b 2 gh
8 c 3 gh
9 c 1 cd
10 c 2 ef
11 c 3 gh
交叉表
这个 returns 频率 table 表示每个类别一起观察的频率:
crosstab = pd.crosstab([df["group1"], df["group2"]], df["item"])
print(crosstab)
item ab cd ef gh zx
group1 group2
a 1 0 1 1 0 0
2 0 0 1 0 0
3 0 0 0 1 0
b 1 1 0 0 0 0
2 0 0 0 1 1
3 1 0 0 0 0
c 1 0 1 0 0 0
2 0 0 1 0 0
3 0 0 0 2 0
将计数强制转换为虚拟代码
由于我们想要伪代码,而不是计算类别的共现,我们可以使用一个快速的技巧来强制所有大于 0 gt(0)
的值变为 1 astype(int)
item ab cd ef gh zx
group1 group2
a 1 0 1 1 0 0
2 0 0 1 0 0
3 0 0 0 1 0
b 1 1 0 0 0 0
2 0 0 0 1 1
3 1 0 0 0 0
c 1 0 1 0 0 0
2 0 0 1 0 0
3 0 0 0 1 0
您可以通过多种技巧在一行中完成。
1) 联结中的唯一索引计数与铸造为 bool
在任何情况下都有效,即使除了 index
、columns
和 values
之外没有任何其他列。此代码意味着计算每个索引列交集的唯一索引,并 returning 1
以防其超过 0
else 0
.
df.reset_index().pivot_table(index=['cust_id','purchase_qtr'],
columns='purchase_item',
values='index',
aggfunc='nunique', fill_value=0)\
.astype(bool).astype(int)
2) 检查是否有任何其他列不为空
如果您除了 index
、columns
和 values
之外还有其他列,并且想将它们用于直觉。就像你的 purchase_date
一样。它更直观,因为您可以像这样“阅读”它:如果商品的购买日期不为空,则每季度检查每个客户并将它们解析为整数。
df.pivot_table(index=['cust_id','purchase_qtr'],
columns='purchase_item',values='purchase_date',
aggfunc=lambda x: all(pd.notna(x)), fill_value=0)\
.astype(int)
3) 查看 len
个元素落入每个索引列交集
这会看到 len
个元素落在每个索引列交集中,并且 returning 1
以防超过 0
else 0
。同样直观的方法:
df.pivot_table(index=['cust_id','purchase_qtr'],
columns='purchase_item',
values='purchase_date',
aggfunc=len, fill_value=0)\
.astype(bool).astype(int)
所有 return 所需的数据帧:
请注意,当您还没有数据框时,您应该只使用 crosstab
,因为它会在内部调用 pivot_table
。