如何使用 python/pandas/numpy 将 sql table 从行旋转到列
how to pivot a sql table from rows to columns with python/pandas/numpy
我有一个字典 table 带有位掩码 ID
见下文:
我想将其转换为以下结构:
每行的标签将成为一列,其值将是组合(按位)。
示例:
值 3 是 1 和 2 的组合,因此 a 将被赋予 1,b 将被赋予 1,其余所有列均为 0
我使用 SQL 服务器存储过程和按位运算符“&”实现了它。
我想使用 python 实现这个转换(我假设它会用 pandas 完成),
每个标签都是 2 的 n 次方,所以我尝试使用从十进制到二进制的转换来解决它 - 这正是我需要的,但我错过了如何将每一位附加到正确的列
示例 3 在二进制中表示为 11,因此我想将 a 分配为 1,将 b 分配为 1,其余所有应为 0。
源 table 可以添加额外的条目,因此输出应该改变目标 table 新行(例如 n , 4096)作为新列 m 将被分配 1或 0,具体取决于值。
关于如何使用 python/pandas 解决此问题的任何建议?
使用带移位 (>>
) 的 numpy 广播将整数转换为由二进制填充的列,最后使用具有所有组合的新列 DataFrame.dot
以及列名和分隔符:
df = pd.DataFrame({'mask_id':range(1, 17)})
#list or Series of tags
L = list('abcdefghijklm')
#L = df2['Tags']
a = df.mask_id.to_numpy()
n = len(L)
data = (a[:, None] >> np.arange(n)) & 1
df1 = pd.DataFrame(data, index=df.index, columns=L)
df1['combinations'] = df1.dot(df1.columns + ',').str.rstrip(',')
print (df1)
a b c d e f g h i j k l m combinations
0 1 0 0 0 0 0 0 0 0 0 0 0 0 a
1 0 1 0 0 0 0 0 0 0 0 0 0 0 b
2 1 1 0 0 0 0 0 0 0 0 0 0 0 a,b
3 0 0 1 0 0 0 0 0 0 0 0 0 0 c
4 1 0 1 0 0 0 0 0 0 0 0 0 0 a,c
5 0 1 1 0 0 0 0 0 0 0 0 0 0 b,c
6 1 1 1 0 0 0 0 0 0 0 0 0 0 a,b,c
7 0 0 0 1 0 0 0 0 0 0 0 0 0 d
8 1 0 0 1 0 0 0 0 0 0 0 0 0 a,d
9 0 1 0 1 0 0 0 0 0 0 0 0 0 b,d
10 1 1 0 1 0 0 0 0 0 0 0 0 0 a,b,d
11 0 0 1 1 0 0 0 0 0 0 0 0 0 c,d
12 1 0 1 1 0 0 0 0 0 0 0 0 0 a,c,d
13 0 1 1 1 0 0 0 0 0 0 0 0 0 b,c,d
14 1 1 1 1 0 0 0 0 0 0 0 0 0 a,b,c,d
15 0 0 0 0 1 0 0 0 0 0 0 0 0 e
如果列表中需要组合使用列表理解:
cols = df1.columns.to_numpy()
df1['combinations'] = [cols[x].tolist() for x in df1.to_numpy().astype(bool)]
print (df1)
a b c d e f g h i j k l m combinations
0 1 0 0 0 0 0 0 0 0 0 0 0 0 [a]
1 0 1 0 0 0 0 0 0 0 0 0 0 0 [b]
2 1 1 0 0 0 0 0 0 0 0 0 0 0 [a, b]
3 0 0 1 0 0 0 0 0 0 0 0 0 0 [c]
4 1 0 1 0 0 0 0 0 0 0 0 0 0 [a, c]
5 0 1 1 0 0 0 0 0 0 0 0 0 0 [b, c]
6 1 1 1 0 0 0 0 0 0 0 0 0 0 [a, b, c]
7 0 0 0 1 0 0 0 0 0 0 0 0 0 [d]
8 1 0 0 1 0 0 0 0 0 0 0 0 0 [a, d]
9 0 1 0 1 0 0 0 0 0 0 0 0 0 [b, d]
10 1 1 0 1 0 0 0 0 0 0 0 0 0 [a, b, d]
11 0 0 1 1 0 0 0 0 0 0 0 0 0 [c, d]
12 1 0 1 1 0 0 0 0 0 0 0 0 0 [a, c, d]
13 0 1 1 1 0 0 0 0 0 0 0 0 0 [b, c, d]
14 1 1 1 1 0 0 0 0 0 0 0 0 0 [a, b, c, d]
15 0 0 0 0 1 0 0 0 0 0 0 0 0 [e]
假设您需要二进制表示,这里是一个不需要先前数据集的表示:
cols = ['a','b','c','d','e','f','g','h','i','j','k','l']
df = [list(('0'*(12-1)+"{0:b}".format(1))[::-1])]
for i in range(16):
n = "{0:b}".format(i)
df = df + [list(('0'*(12-len(n))+n)[::-1])]
df = pd.DataFrame(df, columns = cols)
df["combinations"] = df.apply(lambda x: list(x[x == '1'].index) ,axis = 1)
输出:
a b c d e f g h i j k l combinations
0 1 0 0 0 0 0 0 0 0 0 0 0 [a]
1 0 0 0 0 0 0 0 0 0 0 0 0 []
2 1 0 0 0 0 0 0 0 0 0 0 0 [a]
3 0 1 0 0 0 0 0 0 0 0 0 0 [b]
4 1 1 0 0 0 0 0 0 0 0 0 0 [a, b]
5 0 0 1 0 0 0 0 0 0 0 0 0 [c]
6 1 0 1 0 0 0 0 0 0 0 0 0 [a, c]
7 0 1 1 0 0 0 0 0 0 0 0 0 [b, c]
8 1 1 1 0 0 0 0 0 0 0 0 0 [a, b, c]
9 0 0 0 1 0 0 0 0 0 0 0 0 [d]
10 1 0 0 1 0 0 0 0 0 0 0 0 [a, d]
11 0 1 0 1 0 0 0 0 0 0 0 0 [b, d]
12 1 1 0 1 0 0 0 0 0 0 0 0 [a, b, d]
13 0 0 1 1 0 0 0 0 0 0 0 0 [c, d]
14 1 0 1 1 0 0 0 0 0 0 0 0 [a, c, d]
15 0 1 1 1 0 0 0 0 0 0 0 0 [b, c, d]
16 1 1 1 1 0 0 0 0 0 0 0 0 [a, b, c, d]
我有一个字典 table 带有位掩码 ID 见下文:
我想将其转换为以下结构: 每行的标签将成为一列,其值将是组合(按位)。
示例: 值 3 是 1 和 2 的组合,因此 a 将被赋予 1,b 将被赋予 1,其余所有列均为 0
我使用 SQL 服务器存储过程和按位运算符“&”实现了它。 我想使用 python 实现这个转换(我假设它会用 pandas 完成), 每个标签都是 2 的 n 次方,所以我尝试使用从十进制到二进制的转换来解决它 - 这正是我需要的,但我错过了如何将每一位附加到正确的列 示例 3 在二进制中表示为 11,因此我想将 a 分配为 1,将 b 分配为 1,其余所有应为 0。
源 table 可以添加额外的条目,因此输出应该改变目标 table 新行(例如 n , 4096)作为新列 m 将被分配 1或 0,具体取决于值。
关于如何使用 python/pandas 解决此问题的任何建议?
使用带移位 (>>
) 的 numpy 广播将整数转换为由二进制填充的列,最后使用具有所有组合的新列 DataFrame.dot
以及列名和分隔符:
df = pd.DataFrame({'mask_id':range(1, 17)})
#list or Series of tags
L = list('abcdefghijklm')
#L = df2['Tags']
a = df.mask_id.to_numpy()
n = len(L)
data = (a[:, None] >> np.arange(n)) & 1
df1 = pd.DataFrame(data, index=df.index, columns=L)
df1['combinations'] = df1.dot(df1.columns + ',').str.rstrip(',')
print (df1)
a b c d e f g h i j k l m combinations
0 1 0 0 0 0 0 0 0 0 0 0 0 0 a
1 0 1 0 0 0 0 0 0 0 0 0 0 0 b
2 1 1 0 0 0 0 0 0 0 0 0 0 0 a,b
3 0 0 1 0 0 0 0 0 0 0 0 0 0 c
4 1 0 1 0 0 0 0 0 0 0 0 0 0 a,c
5 0 1 1 0 0 0 0 0 0 0 0 0 0 b,c
6 1 1 1 0 0 0 0 0 0 0 0 0 0 a,b,c
7 0 0 0 1 0 0 0 0 0 0 0 0 0 d
8 1 0 0 1 0 0 0 0 0 0 0 0 0 a,d
9 0 1 0 1 0 0 0 0 0 0 0 0 0 b,d
10 1 1 0 1 0 0 0 0 0 0 0 0 0 a,b,d
11 0 0 1 1 0 0 0 0 0 0 0 0 0 c,d
12 1 0 1 1 0 0 0 0 0 0 0 0 0 a,c,d
13 0 1 1 1 0 0 0 0 0 0 0 0 0 b,c,d
14 1 1 1 1 0 0 0 0 0 0 0 0 0 a,b,c,d
15 0 0 0 0 1 0 0 0 0 0 0 0 0 e
如果列表中需要组合使用列表理解:
cols = df1.columns.to_numpy()
df1['combinations'] = [cols[x].tolist() for x in df1.to_numpy().astype(bool)]
print (df1)
a b c d e f g h i j k l m combinations
0 1 0 0 0 0 0 0 0 0 0 0 0 0 [a]
1 0 1 0 0 0 0 0 0 0 0 0 0 0 [b]
2 1 1 0 0 0 0 0 0 0 0 0 0 0 [a, b]
3 0 0 1 0 0 0 0 0 0 0 0 0 0 [c]
4 1 0 1 0 0 0 0 0 0 0 0 0 0 [a, c]
5 0 1 1 0 0 0 0 0 0 0 0 0 0 [b, c]
6 1 1 1 0 0 0 0 0 0 0 0 0 0 [a, b, c]
7 0 0 0 1 0 0 0 0 0 0 0 0 0 [d]
8 1 0 0 1 0 0 0 0 0 0 0 0 0 [a, d]
9 0 1 0 1 0 0 0 0 0 0 0 0 0 [b, d]
10 1 1 0 1 0 0 0 0 0 0 0 0 0 [a, b, d]
11 0 0 1 1 0 0 0 0 0 0 0 0 0 [c, d]
12 1 0 1 1 0 0 0 0 0 0 0 0 0 [a, c, d]
13 0 1 1 1 0 0 0 0 0 0 0 0 0 [b, c, d]
14 1 1 1 1 0 0 0 0 0 0 0 0 0 [a, b, c, d]
15 0 0 0 0 1 0 0 0 0 0 0 0 0 [e]
假设您需要二进制表示,这里是一个不需要先前数据集的表示:
cols = ['a','b','c','d','e','f','g','h','i','j','k','l']
df = [list(('0'*(12-1)+"{0:b}".format(1))[::-1])]
for i in range(16):
n = "{0:b}".format(i)
df = df + [list(('0'*(12-len(n))+n)[::-1])]
df = pd.DataFrame(df, columns = cols)
df["combinations"] = df.apply(lambda x: list(x[x == '1'].index) ,axis = 1)
输出:
a b c d e f g h i j k l combinations
0 1 0 0 0 0 0 0 0 0 0 0 0 [a]
1 0 0 0 0 0 0 0 0 0 0 0 0 []
2 1 0 0 0 0 0 0 0 0 0 0 0 [a]
3 0 1 0 0 0 0 0 0 0 0 0 0 [b]
4 1 1 0 0 0 0 0 0 0 0 0 0 [a, b]
5 0 0 1 0 0 0 0 0 0 0 0 0 [c]
6 1 0 1 0 0 0 0 0 0 0 0 0 [a, c]
7 0 1 1 0 0 0 0 0 0 0 0 0 [b, c]
8 1 1 1 0 0 0 0 0 0 0 0 0 [a, b, c]
9 0 0 0 1 0 0 0 0 0 0 0 0 [d]
10 1 0 0 1 0 0 0 0 0 0 0 0 [a, d]
11 0 1 0 1 0 0 0 0 0 0 0 0 [b, d]
12 1 1 0 1 0 0 0 0 0 0 0 0 [a, b, d]
13 0 0 1 1 0 0 0 0 0 0 0 0 [c, d]
14 1 0 1 1 0 0 0 0 0 0 0 0 [a, c, d]
15 0 1 1 1 0 0 0 0 0 0 0 0 [b, c, d]
16 1 1 1 1 0 0 0 0 0 0 0 0 [a, b, c, d]