根据条件替换数据框列中的值

ozh*_*gin 5 python dataframe pandas

我有一个看似简单的任务.具有2列的数据帧:A和B.如果B中的值大于A中的值 - 用值A替换这些值.我曾经这样做过df.B[df.B > df.A] = df.A,但是最近的pandas升级开始给出了SettingWithCopyWarning遇到此链式赋值的时间.官方文档建议使用.loc.

好吧,我说,并且完成了它df.loc[df.B > df.A, 'B'] = df.A并且一切正常,除非B列具有所有值NaN.然后发生了一些奇怪的事:

In [1]: df = pd.DataFrame({'A': [1, 2, 3],'B': [np.NaN, np.NaN, np.NaN]})

In [2]: df
Out[2]: 
   A   B
0  1 NaN
1  2 NaN
2  3 NaN

In [3]: df.loc[df.B > df.A, 'B'] = df.A

In [4]: df
Out[4]: 
   A                    B
0  1 -9223372036854775808
1  2 -9223372036854775808
2  3 -9223372036854775808
Run Code Online (Sandbox Code Playgroud)

现在,如果B中的一个元素满足条件(大于A),那么一切正常:

In [1]: df = pd.DataFrame({'A': [1, 2, 3],'B': [np.NaN, 4, np.NaN]})

In [2]: df
Out[2]: 
   A   B
0  1 NaN
1  2   4
2  3 NaN

In [3]: df.loc[df.B > df.A, 'B'] = df.A

In [4]: df
Out[4]: 
   A   B
0  1 NaN
1  2   2
2  3 NaN
Run Code Online (Sandbox Code Playgroud)

但是如果没有Bs元素满足,那么所有NaNs都会替换为-9223372036854775808:

In [1]: df = pd.DataFrame({'A':[1,2,3],'B':[np.NaN,1,np.NaN]})

In [2]: df
Out[2]: 
   A   B
0  1 NaN
1  2   1
2  3 NaN

In [3]: df.loc[df.B > df.A, 'B'] = df.A

In [4]: df
Out[4]: 
   A                    B
0  1 -9223372036854775808
1  2                    1
2  3 -9223372036854775808
Run Code Online (Sandbox Code Playgroud)

这是一个错误还是一个功能?我该怎么做这个替换?

谢谢!

Jef*_*eff 8

这是一个在这里修复的buggie .

由于pandas基本上允许在loc中的表达式的右侧设置任何内容,因此可能需要消除10个以上的情况需要消除歧义.给你一个想法:

df.loc[lhs, column] = rhs 
Run Code Online (Sandbox Code Playgroud)

其中rhs可能是:list,array,scalar和lhs可能是:slice,tuple,scalar,array

以及需要根据rhs推断/设置得到的列的dtype的一小部分情况.(这有点复杂).例如,假设你没有在lhs上设置所有元素并且它是整数,那么你需要强制浮动.但是如果你确实设置了所有元素并且rhs是一个整数,那么它需要被强制转换为整数.

在这个特殊情况下,lhs是一个数组,所以我们通常会尝试将lhs强制转换为rhs的类型,但如果我们有一个不安全的转换(int - > float),这种情况就会退化

我只想说这是一个缺失的边缘案例.