问题描述
我有一个带位掩码ID的字典表 见下文:
我想将其转换为以下结构: 每行的标签将变成一列,其值将是(按位)组合。
示例: 值3是 1和2 的组合,因此a将被赋予1,b将被赋予1,其余所有列均为0
我已经使用带有按位运算符“&”的SQL Server存储过程实现了它。 我想使用python来实现此转换(我假设它将通过pandas完成), 您可以将每个标签的2乘以n的幂,所以我尝试使用从十进制到二进制的转换来解决它-正是我所需要的,但是我错过了将每一位附加到n的阶段。正确的专栏 示例3以二进制形式表示为11,因此我想为a分配1,将b分配为1,其余所有应为0。
可能在源表中添加了其他条目,因此输出应将目标表更改为新行(例如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,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,d
14 1 1 1 1 0 0 0 0 0 0 0 0 0 a,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,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,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,d]
13 0 1 1 1 0 0 0 0 0 0 0 0 0 [b,d]
14 1 1 1 1 0 0 0 0 0 0 0 0 0 [a,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,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,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,d]
15 0 1 1 1 0 0 0 0 0 0 0 0 [b,d]
16 1 1 1 1 0 0 0 0 0 0 0 0 [a,d]