快速将Pandas系列标签转换为相应列中的间接值系列

时间:2019-10-12 16:12:55

标签: python pandas dataframe

我有以下示例数据框:

N = np.arange(1, 10)
df = pd.DataFrame({
    'ref': [ 'a',  'b',  'c',  'd',  'c',  'b',  'a',  'b',  'c'],
    'a':   [   1,    2,    3,    4,    5,    6,    7,    8,    9],
    'b':   [  10,   20,   30,   40,   50,   60,   70,   80,   90],
    'c':   [ 100,  200,  300,  400,  500,  600,  700,  800,  900],
    'd':   [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000],
})

我想以某种方式“取消引用” ref列以获取此信息:

    'ref': [ 'a',  'b',  'c',  'd',  'c',  'b',  'a',  'b',  'c'],
    'ind': [   1,   20,  300, 4000,  500,   60,    7,   80,  900],

因此ind中的每个值都应与ref标记的列中的值在同一位置对应。

朴素的方法是使用类似df[df['ref']]的东西,然后乘以单位矩阵,然后按列求和。但是,由于我有很大的(〜8 GB)数据帧,因此我猜这样做会使其大小几乎平方。而且感觉不对。

此外,由于大小的原因,它的迭代速度非常慢。而且我无法使用Cython进行迭代,因为将此数据帧转换为numpy数组会丢失标签信息,而我需要正确地找到该列。

有什么建议吗?..

3 个答案:

答案 0 :(得分:1)

您可以使用DataFrame.mask或numpy进行操作,如下图所示numpy在此数据集中的效果要好一些

N = np.arange(1, 10)
df_b = pd.DataFrame({
    'ref': [ 'a',  'b',  'c',  'd',  'c',  'b',  'a',  'b',  'c'],
    'a':   [   1,    2,    3,    4,    5,    6,    7,    8,    9],
    'b':   [  10,   20,   30,   40,   50,   60,   70,   80,   90],
    'c':   [ 100,  200,  300,  400,  500,  600,  700,  800,  900],
    'd':   [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000],
})

df_b

在哪里使用熊猫

%%timeit
df = df_b.copy()
cols = df.columns[1:]
df["ind"] = df["ref"]

for col in cols:
    df.ind.mask(df.ind==col, df[col], inplace=True)
df
## 6.73 ms ± 129 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

使用Numpy的位置

%%timeit
df = df_b.copy()
arr = df.ref.values

cols = df.columns[1:]
for col in cols:
    arr2 = df[col].values
    arr = np.where(arr==col, arr2, arr)

df["ind"] = arr
df

## 1.21 ms ± 73 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

结果

    ref a   b   c   d   ind
0   a   1   10  100 1000    1
1   b   2   20  200 2000    20
2   c   3   30  300 3000    300
3   d   4   40  400 4000    4000
4   c   5   50  500 5000    500
5   b   6   60  600 6000    60
6   a   7   70  700 7000    7
7   b   8   80  800 8000    80
8   c   9   90  900 9000    900

答案 1 :(得分:0)

使用pandas.lookup()

df['ind'] = df.lookup(df.index, df['ref'])

  ref  a   b    c     d   ind
0   a  1  10  100  1000     1
1   b  2  20  200  2000    20
2   c  3  30  300  3000   300
3   d  4  40  400  4000  4000
4   c  5  50  500  5000   500
5   b  6  60  600  6000    60
6   a  7  70  700  7000     7
7   b  8  80  800  8000    80
8   c  9  90  900  9000   900

答案 2 :(得分:0)

您可以使用numpy索引:

lookup = dict(zip(df.columns, range(len(df.columns))))
result = pd.DataFrame({ 'ref' : df.ref, 'ind': df.values[np.arange(len(df)), df.ref.map(lookup)] })

print(result)

输出

  ref   ind
0   a     1
1   b    20
2   c   300
3   d  4000
4   c   500
5   b    60
6   a     7
7   b    80
8   c   900