Замена запредельных (комплексных) значений в фрейме данных pandas



(Python 2.7, pandas 0.13.0)



Фон: я читаю кучу данных из CSV-файла и загружаю их в фрейм данных pandas. Некоторые данные являются сложными (я преобразую их из строк при загрузке). Некоторые из значений были погрешностями оборудования, отличающимися тем, что они слишком велики. Я хочу заменить все значения, величина которых превышает определенный порог, на np.бабушка. Это легко с массивом numpy (при условии, что вы используете "сложный nan", как показано на рисунке), но было сложно в pandas. Я задокументировал шаги, которые я попробовал ниже - последняя попытка почти достигает этого, но любая строка, где происходит замена, преобразуется в реальную.



В этот момент я думаю о том, чтобы просто вытянуть значения в массив numpy, изменить, а затем загрузить обратно в фрейм данных, но это кажется довольно неэлегантным.



EDIT: решение, приведенное ниже, работает, но мне интересно, есть ли еще ошибка в том, как панды обращаются с НАН. в коде, который я написал. Похоже, что созданный НАН-это nan +0.j вместо nan +nanj. Matplotlib построит график последнего без проблем, если вы делаете что-то вроде plot(np.real(signal), np.imag(signal)), но не любит первый, так как он строит пару (Nan, 0). Похоже, мне нужно заменить новые записи nan +0j на записи nan +nanj, что рекурсивно перезапускает проблему. :)



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
479   1  

1 ответ:

Похоже, что это работает без флага 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-хорошая идея (хотя это, вероятно, ошибка ):

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

Comments

    Ничего не найдено.