Skip to main content
 首页 » 编程设计

python之替换 pandas DataFrame 中的越界(复杂)值

2025年05月04日11傻小

(Python 2.7, Pandas 0.13.0)

背景:我从 CSV 文件中读取了一堆数据并将其加载到 pandas 数据框中。有些数据很复杂(我在加载时将其从字符串转换而来)。一些值是设备错误,以太大为特征。我想用 np.nan 替换所有幅度超过某个阈值的值。使用 numpy 数组很容易(假设您使用如图所示的“复杂 nan”),但在 Pandas 中一直具有挑战性。我在下面记录了我尝试过的步骤 - 最后一次尝试几乎完成了,但是发生替换的任何行都被转换为真实的。

在这一点上,我想简单地将值拉入一个 numpy 数组,进行修改,然后加载回数据框,但这似乎相当不雅观。

编辑:下面的解决方案有效,但我想知道在我编写的代码中 pandas 处理 NaN. 的方式是否仍然存在错误。看起来创建的 NaN 是 nan +0.j 而不是 nan +nanj。 如果你正在做类似plot(np.real(signal), np.imag(signal))的事情,Matplotlib 将毫无问题地绘制后者,但不喜欢前者,因为它是绘制 (Nan, 0) 对。看起来我需要用 nan +nanj 条目替换新的 nan +0j 条目,这会递归地重新启动问题。 :)

EDIT2:NaN 中确实存在视觉差异,但我发现的新错误与该差异无关。差异可能并不重要。删除线上方的内容不正确。

# begin by making a fake data set that resembles the CSV struction 
headers = ['Z1', 'Z2', 'Z3'] 
temp = np.arange(12).reshape((4,3)) + 1j*np.arange(12,24).reshape((4,3)) 
temp[0,1] = 5000 + 1j*5000 
temp[1,1] = 5000 + 1j*8000 
temp[2,2] = 7000 + 1j*3000 
junk = ['exists to', 'make life', 'extra', 'difficult'] 
df_junk = pd.DataFrame(data=junk, columns=['other junk']) 
df = pd.DataFrame(data=temp, columns=headers) 
df = pd.concat((df, df_junk), axis=1) 
# very simple to do this in an np.array if we only take the numbers 
temp2 = np.copy(temp) 
# temp2 is the desired result, but in the frame with everything else 
temp2[ np.abs(temp2) > 5000 ] = np.nan + 1j*np.nan 
df2 = df.copy() 
 
# Executing the next line replaces the value with NaN, 
# but turns all of column Z2 into real numbers 
#df[np.abs(df[headers]) > 5000 ] = np.nan + 1j*np.nan 
# Trying to grab the index first gives 
# ValueError: Cannot index with multidimensional key 
#df.ix[np.abs(df[headers]) > 5000 ] 
for column in headers: 
    # The following line would turn the entire 3rd row into NaN 
    # df[np.abs(df[column]) > 5000] = np.nan + 1j*np.nan 
    # Attempts along these lines to apply a lambda (tried different ones) 
    # didn't seem to work 
    #csv_data[column] = csv_data[column].apply(lambda x:\ 
    # pd.replace(x, np.nan) if abs(x) > 5000 else pd.replace(x,x)) 
    # This last one almost works, but again turns columns with replacements into reals 
    df2[column].where(abs(df2[column]) <= 5000, np.nan+1j*np.nan, inplace=True) 
 
        Z1  Z2  Z3 other junk 
0      12j NaN   2  exists to 
1  (3+15j) NaN   5  make life 
2  (6+18j)   7 NaN      extra 
3  (9+21j)  10  11  difficult 

请您参考如下方法:

看起来这在没有 inplace 标志的情况下有效:

In [11]: df3 = df2[['Z1', 'Z2', 'Z3']] 
 
In [12]: df3.where(df3 <= 5000)  # replaces by NaN by default 
Out[12]: 
        Z1        Z2        Z3 
0      12j       NaN   (2+14j) 
1  (3+15j)       NaN   (5+17j) 
2  (6+18j)   (7+19j)       NaN 
3  (9+21j)  (10+22j)  (11+23j) 
 
In [13]: df2[['Z1', 'Z2', 'Z3']] = df3.where(df3 <= 5000) 

通常我认为避免 inplace 标志是个好主意(尽管这可能是 bug ):

In [21]: df3.where(df3 <= 5000, inplace=True) 
 
In [22]: df3 
Out[22]: 
        Z1  Z2  Z3 
0      12j NaN   2 
1  (3+15j) NaN   5 
2  (6+18j)   7 NaN 
3  (9+21j)  10  11