有效地将列中的值替换为另一列Pandas DataFrame

Pab*_*blo 9 python replace dataframe pandas

我有一个像下面这样的Pandas DataFrame:

   col1 col2 col3
1   0.2  0.3  0.3
2   0.2  0.3  0.3
3     0  0.4  0.4
4     0    0  0.3
5     0    0    0
6   0.1  0.4  0.4
Run Code Online (Sandbox Code Playgroud)

我希望仅在值等于0 col1时将值替换为第二列(col2)中的col1值,并且在(对于剩余的零值)之后,再次使用第三列(col3)进行替换.期望的结果是下一个:

   col1 col2 col3
1   0.2  0.3  0.3
2   0.2  0.3  0.3
3   0.4  0.4  0.4
4   0.3    0  0.3
5     0    0    0
6   0.1  0.4  0.4
Run Code Online (Sandbox Code Playgroud)

我使用该pd.replace功能做到了,但它似乎太慢了......我认为必须是一种更快的方法来实现它.

df.col1.replace(0,df.col2,inplace=True)
df.col1.replace(0,df.col3,inplace=True)
Run Code Online (Sandbox Code Playgroud)

有更快的方法吗?使用其他功能而不是pd.replace功能?

roo*_*oot 19

使用np.where速度更快.使用与您使用的类似模式replace:

df['col1'] = np.where(df['col1'] == 0, df['col2'], df['col1'])
df['col1'] = np.where(df['col1'] == 0, df['col3'], df['col1'])
Run Code Online (Sandbox Code Playgroud)

但是,使用嵌套np.where稍快一些:

df['col1'] = np.where(df['col1'] == 0, 
                      np.where(df['col2'] == 0, df['col3'], df['col2']),
                      df['col1'])
Run Code Online (Sandbox Code Playgroud)

计时

使用以下设置生成更大的示例DataFrame和计时功能:

df = pd.concat([df]*10**4, ignore_index=True)

def root_nested(df):
    df['col1'] = np.where(df['col1'] == 0, np.where(df['col2'] == 0, df['col3'], df['col2']), df['col1'])
    return df

def root_split(df):
    df['col1'] = np.where(df['col1'] == 0, df['col2'], df['col1'])
    df['col1'] = np.where(df['col1'] == 0, df['col3'], df['col1'])
    return df

def pir2(df):
    df['col1'] = df.where(df.ne(0), np.nan).bfill(axis=1).col1.fillna(0)
    return df

def pir2_2(df):
    slc = (df.values != 0).argmax(axis=1)
    return df.values[np.arange(slc.shape[0]), slc]

def andrew(df):
    df.col1[df.col1 == 0] = df.col2
    df.col1[df.col1 == 0] = df.col3
    return df

def pablo(df):
    df['col1'] = df['col1'].replace(0,df['col2'])
    df['col1'] = df['col1'].replace(0,df['col3'])
    return df
Run Code Online (Sandbox Code Playgroud)

我得到以下时间:

%timeit root_nested(df.copy())
100 loops, best of 3: 2.25 ms per loop

%timeit root_split(df.copy())
100 loops, best of 3: 2.62 ms per loop

%timeit pir2(df.copy())
100 loops, best of 3: 6.25 ms per loop

%timeit pir2_2(df.copy())
1 loop, best of 3: 2.4 ms per loop

%timeit andrew(df.copy())
100 loops, best of 3: 8.55 ms per loop
Run Code Online (Sandbox Code Playgroud)

我试过计时你的方法,但它已经运行了几分钟而没有完成.作为比较,仅在6行示例上对您的方法进行计时DataFrame(不是上面测试的大得多)花了12.8 ms.


And*_*rew 6

我不确定它是否更快,但您可以对数据帧进行切片以获得所需结果.

df.col1[df.col1 == 0] = df.col2
df.col1[df.col1 == 0] = df.col3
print(df)
Run Code Online (Sandbox Code Playgroud)

输出:

   col1  col2  col3
0   0.2   0.3   0.3
1   0.2   0.3   0.3
2   0.4   0.4   0.4
3   0.3   0.0   0.3
4   0.0   0.0   0.0
5   0.1   0.4   0.4
Run Code Online (Sandbox Code Playgroud)

或者,如果你想要它更简洁(虽然我不知道它是否更快)你可以将你所做的与你所做的结合起来.

df.col1[df.col1 == 0] = df.col2.replace(0, df.col3)
print(df)
Run Code Online (Sandbox Code Playgroud)

输出:

   col1  col2  col3
0   0.2   0.3   0.3
1   0.2   0.3   0.3
2   0.4   0.4   0.4
3   0.3   0.0   0.3
4   0.0   0.0   0.0
5   0.1   0.4   0.4
Run Code Online (Sandbox Code Playgroud)