Bagaimana cara menghitung mean, menghilangkan NaN dan outlier dari kerangka data dalam format ini?

Saya memiliki kerangka data dalam format di bawah ini:

Original Dataframe

    |  x  |  value1  |  value2  |  value3  |  value4
 ---|-----|----------|----------|----------|-----------
  0 |  1  |    1     |   NaN    |    3     |   1
  1 |  2  |    4     |   NaN    |    1     |   NaN
  2 |  3  |    2     |    6     |    1     |   2
  3 |  4  |    1     |    1     |    2     |   1

Tujuan saya adalah mendapatkan nilai rata-rata, untuk setiap baris, menghilangkan NaN dan juga menghilangkan outlier. Tujuannya adalah untuk mencapai kerangka data baru dengan format berikut:

Desired Dataframe

    |  x  |  mean (after dropping the NaN and the outliers)*
 ---|-----|--------
  0 |  1  |   a
  1 |  2  |   b   
  2 |  3  |   c   
  3 |  4  |   d   

*Perhatikan bahwa a, b, c, d adalah nilai rata-rata (saya tidak menghitung hasilnya)


Tujuan akhir setelah mencapai hasil adalah mencetak grafik nilai dari waktu ke waktu.


Bekerja dengan satu daftar nilai, misalnya setara dengan satu kolom nilai dan satu kolom indeks, saya bisa melakukan semua operasi: hapus NaN, hitung skor Z, lalu kembalikan daftar nilai, seperti yang ditunjukkan di bawah:

import pandas as pd   
import numpy as np
from scipy import stats

data = {'value': [1, 2, 15, np.NaN, 2, 2, 2, 3, 1, 1], 
        'x': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
df = pd.DataFrame(data)

df.dropna(inplace=True)
df = df[(np.abs(stats.zscore(df['return'])) < 2)]

Ada beberapa masalah yang muncul ketika saya mencoba bekerja secara massal (dan saya yakin masalah tersebut muncul karena saya terbiasa memprogram menggunakan loop dan harus ada cara yang "pintar" untuk melakukan operasi ini di Pandas.)

Saya tidak bisa menghitung skor Z ketika ada nilai NaN. Saya mendapat kesalahan ini:

/home/jupyterlab/conda/lib/python3.6/site-packages/ipykernel_launcher.py:14: RuntimeWarning: invalid value encountered in less

Jadi saya tahu bahwa saya harus menghilangkan NaN. Tetapi saya tidak dapat melakukannya dalam format kerangka data ini karena ini berarti menghilangkan baris atau kolom yang mengakibatkan hilangnya informasi.

Pendekatan lain yang saya coba namun tidak berhasil adalah mengubah tabel ini menjadi bentuk panjang, artinya saya akan mendapatkan:

    |  x  |  valueName  |  actualValue
 ---|-----|-------------|--------------
  0 |  1  |  value1     |      1       
  1 |  1  |  value2     |     NaN    
 ...  ...      ...            ...
  2 |  2  |  value2     |      4  
  3 |  2  |  value2     |     NaN

Hal ini membuat saya menjatuhkan Nan, tetapi untuk menggunakan skor Z lebih bermasalah. Saya yakin ini adalah masalah umum, tetapi saya tidak tahu cara mengatasinya.


person Dan    schedule 27.03.2019    source sumber
comment
bagaimana dengan mengubah NaN menjadi 0 ?   -  person Sociopath    schedule 27.03.2019
comment
Saya rasa pertanyaan Anda telah terjawab di sini   -  person Yohai Magan    schedule 27.03.2019
comment
Kemungkinan duplikat bagaimana cara zscore menormalkan kolom panda dengan nans?   -  person Yohai Magan    schedule 27.03.2019
comment
Hai AhshayNevrekar, jika saya melakukan itu, maksudnya akan terpengaruh. Dalam hal ini, , 0.0, atau NaN berarti dilarang masuk.   -  person Dan    schedule 27.03.2019
comment
Hai yochay magan, link yang Anda posting mengacu pada rangkaian satu dimensi, yang dapat saya tangani hanya dengan menggunakan metode dropna.   -  person Dan    schedule 27.03.2019


Jawaban (1)


Anda dapat gunakan:

from scipy import stats

#reshape to MultiIndex Series for remove NaNs
s = df.set_index('x').stack()
print (s)
x        
1  value1    1.0
   value3    3.0
   value4    1.0
2  value1    4.0
   value3    1.0
3  value1    2.0
   value2    6.0
   value3    1.0
   value4    2.0
4  value1    1.0
   value2    1.0
   value3    2.0
   value4    1.0
dtype: float64

#count zsore by first level of group - by x
s1 = s.groupby(level=0).transform(lambda x: np.abs(stats.zscore(x)))
print (s1)
x        
1  value1    0.707107
   value3    1.414214
   value4    0.707107
2  value1    1.000000
   value3    1.000000
3  value1    0.390567
   value2    1.692456
   value3    0.911322
   value4    0.390567
4  value1    0.577350
   value2    0.577350
   value3    1.732051
   value4    0.577350

#filter by condition and get mean by first level x, convert to DataFrame
s2 = s[s1 < 2].mean(level=0).reset_index(name='mean')
print (s2)
   x      mean
0  1  1.666667
1  2  2.500000
2  3  2.750000
3  4  1.250000
person jezrael    schedule 27.03.2019