通过采样其他列的位来创建新列

时间:2019-04-11 16:54:34

标签: python pandas

考虑如下所示的包含N列的数据框。每个条目都是一个8位整数。

|---------------------|------------------|---------------------|
|      Column 1       |     Column 2     |      Column N       |
|---------------------|------------------|---------------------|
|          4          |         8        |          13         |
|---------------------|------------------|---------------------|
|          0          |         32       |          16         |
|---------------------|------------------|---------------------|

我想通过从其余列中随机采样数据的每一位来创建每行有8位条目的新列。因此,结果数据框将如下所示:

|---------------------|------------------|---------------------|---------------|
|      Column 1       |     Column 2     |      Column N       |     Sampled   |
|---------------------|------------------|---------------------|---------------|
|      4 = (100)      |     8 = (1000)   |    13 = (1101)      |   5 = (0101)  |
|---------------------|------------------|---------------------|---------------|
|      0 = (0)        |    32 = (100000) |   16 = (10000)      | 48 = (110000) |
|---------------------|------------------|---------------------|---------------|

通过在同一位置的所有可能位中选择一个位来创建“采样”列中的第一个条目。例如,从{0 (LSB from col 1), 0 (LSB from col 2), 1 (LSB from col N)}中选择第一项中的LSB = 1,依此类推。

这类似于this question,但不是要对每个条目进行采样,而是需要对每个位进行采样。

考虑到数据帧具有大量的行和列,什么是实现此目的的有效方法?基于类似的问题,我假设我们需要一个lookup + sample来选择条目,另一个sample来选择位?

1 个答案:

答案 0 :(得分:2)

与之前执行示例时的逻辑相同,但是这里我用unnesting在二进制和十进制之间进行了两次转换,然后将结果重新加入

df1=df.applymap(lambda x : list('{0:08b}'.format(x)))

df1=unnesting(df1,df1.columns.tolist())
s=np.random.randint(0, df1.shape[1], df1.shape[0])

yourcol=pd.Series(df1.values[np.arange(len(df1)),s]).groupby(df1.index).apply(''.join)

df['Sampled']=yourcol.map(lambda x : int(x,2))

df
Out[268]: 
   c1  c2  cn  Sampled
0   4   8  13       12
1   0  32  16       16

def unnesting(df, explode):
    idx = df.index.repeat(df[explode[0]].str.len())
    df1 = pd.concat([
        pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
    df1.index = idx

    return df1.join(df.drop(explode, 1), how='left')