首页 > 解决方案 > 映射 Serie 和 Dataframe 值

问题描述

我有一个数据框df,其中的列['col_A' , 'col_B', 'col_C']有 1000 行。

我还有一个系列,它以 DataFrame 列的名称和一个介于 0 到 1000 之间的值作为索引。例如:s 就是这样的系列:

Col_A      20
Col_B      0
Col_C      300

我想将数据框更改为:

df.iloc[0:20,0] = a certain value  (column A)

我尝试使用 for 循环进行切片,但它花费了太多时间。有熊猫功能可以做到这一点吗?

我的代码是:

for i in range(0,3):
    df.iloc[0:s.iloc[i]-1,i] = -1

在一般范围内,我有时需要将 Series 索引映射到 Dataframe 列,但很难找到一种快速且消耗更少的方法。

谢谢

标签: pythonpython-3.xpandasnumpy

解决方案


循环

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(0,10, (1000,3)), 
                  columns=['col_A', 'col_B', 'col_C'])

s = pd.Series([20,0,300], 
              index=['col_A', 'col_B', 'col_C'])

for col, idx in s.iteritems():
    df.loc[:idx, col] = -1

df
     col_A  col_B  col_C
0     -999   -999   -999
1     -999      3   -999
2     -999      3   -999
3     -999      2   -999
4     -999      1   -999
..     ...    ...    ...
995      2      6      9
996      1      9      5
997      2      6      4
998      4      0      1
999      9      2      8

熊猫申请

def f(c, s):
    c[:s[c.name]] = -1
    return c

df = df.apply(lambda c: f(c,s))
df 
     col_A  col_B  col_C
0       -1      6     -1
1       -1      1     -1
2       -1      6     -1
3       -1      1     -1
4       -1      6     -1
..     ...    ...    ...
995      2      4      3
996      2      0      0
997      8      5      7
998      3      5      5
999      5      7      7

性能 在我的本地机器上,使用 N=1000,for 循环稍微快一些。将N增加到1M,apply方法更快:

def for_loop(N):
    df = pd.DataFrame(np.random.randint(0,10, (N,3)), 
                  columns=['col_A', 'col_B', 'col_C'])
    for col, idx in s.iteritems():
        df.loc[:idx, col] = -1
    return df

def apply_method(N):

    def f(c, s):
        c[:s[c.name]] = -1
        return c

    return df.apply(lambda c: f(c,s))

%timeit for_loop(1000)
1.19 ms ± 58.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit apply_method(1000)
185 ms ± 44.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit for_loop(1000_000)
303 ms ± 25.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit apply_method(1000_000)
162 ms ± 8.84 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

推荐阅读