python - tablas - seleccionar columnas de un dataframe pandas
Detectar y excluir valores atípicos en el marco de datos de Pandas (10)
Esta respuesta es similar a la proporcionada por @tanemaki, pero usa una expresión lambda
lugar de scipy stats
.
df = pd.DataFrame(np.random.randn(100, 3), columns=list(''ABC''))
df[df.apply(lambda x: np.abs(x - x.mean()) / x.std() < 3).all(axis=1)]
Para filtrar el DataFrame donde solo UNA columna (por ejemplo, "B") se encuentra dentro de tres desviaciones estándar:
df[((df.B - df.B.mean()) / df.B.std()).abs() < 3]
Tengo un marco de datos de pandas con pocas columnas.
Ahora sé que ciertas filas son valores atípicos basados en un cierto valor de columna.
Por ejemplo, columnas: ''Vol'' tiene todos los valores alrededor de 12.xx y un valor que es 4000
Ahora me gustaría excluir aquellas filas que tienen Vol Column como esta.
Entonces, esencialmente necesito poner un filtro para que seleccionemos todas las filas donde los valores de una cierta columna están dentro de, digamos, 3 desviaciones estándar de la media.
¿Cuál es una manera elegante de lograr esto?
Mi función para eliminar valores atípicos
def drop_outliers(df, field_name):
distance = 1.5 * (np.percentile(df[field_name], 75) - np.percentile(df[field_name], 25))
df.drop(df[df[field_name] > distance + np.percentile(df[field_name], 75)].index, inplace=True)
df.drop(df[df[field_name] < np.percentile(df[field_name], 25) - distance].index, inplace=True)
Otra opción es transformar sus datos para que el efecto de los valores atípicos se mitigue. Usted puede hacer esto al personalizar sus datos.
import pandas as pd
from scipy.stats import mstats
%matplotlib inline
test_data = pd.Series(range(30))
test_data.plot()
# Truncate values to the 5th and 95th percentiles
transformed_test_data = pd.Series(mstats.winsorize(test_data, limits=[0.05, 0.05]))
transformed_test_data.plot()
Para cada columna de su marco de datos, puede obtener cuantil con:
q = df["col"].quantile(0.99)
y luego filtrar con:
df[df["col"] < q]
Si le gusta el método de encadenamiento, puede obtener su condición booleana para todas las columnas numéricas como esta:
df.sub(df.mean()).div(df.std()).abs().lt(3)
Cada valor de cada columna se convertirá en True/False
función de si está a menos de tres desviaciones estándar de la media o no.
Si tiene varias columnas en su marco de datos y desea eliminar todas las filas que tienen valores atípicos en al menos una columna, la siguiente expresión lo haría de una vez.
df = pd.DataFrame(np.random.randn(100, 3))
from scipy import stats
df[(np.abs(stats.zscore(df)) < 3).all(axis=1)]
un ejemplo completo con datos y 2 grupos a continuación:
Importaciones:
from StringIO import StringIO
import pandas as pd
#pandas config
pd.set_option(''display.max_rows'', 20)
Ejemplo de datos con 2 grupos: G1: Grupo 1. G2: Grupo 2:
TESTDATA = StringIO("""G1;G2;Value
1;A;1.6
1;A;5.1
1;A;7.1
1;A;8.1
1;B;21.1
1;B;22.1
1;B;24.1
1;B;30.6
2;A;40.6
2;A;51.1
2;A;52.1
2;A;60.6
2;B;80.1
2;B;70.6
2;B;90.6
2;B;85.1
""")
Leer datos de texto en el marco de datos de pandas:
df = pd.read_csv(TESTDATA, sep=";")
Defina los valores atípicos utilizando desviaciones estándar
stds = 1.0
outliers = df[[''G1'', ''G2'', ''Value'']].groupby([''G1'',''G2'']).transform(
lambda group: (group - group.mean()).abs().div(group.std())) > stds
Defina los valores de datos filtrados y los valores atípicos:
dfv = df[outliers.Value == False]
dfo = df[outliers.Value == True]
Imprimir el resultado:
print ''/n''*5, ''All values with decimal 1 are non-outliers. In the other hand, all values with 6 in the decimal are.''
print ''/nDef DATA:/n%s/n/nFiltred Values with %s stds:/n%s/n/nOutliers:/n%s'' %(df, stds, dfv, dfo)
scipy.stats
tiene los métodos trim1()
y trimboth()
para cortar los valores atípicos en una sola fila, de acuerdo con el ranking y un porcentaje introducido de valores eliminados.
Use la indexación boolean
como lo haría en numpy.array
df=pd.DataFrame({''Data'':np.random.normal(size=200)}) #example dataset of normally distributed data.
df[np.abs(df.Data-df.Data.mean())<=(3*df.Data.std())] #keep only the ones that are within +3 to -3 standard deviations in the column ''Data''.
df[~(np.abs(df.Data-df.Data.mean())>(3*df.Data.std()))] #or if you prefer the other way around
Para una serie es similar:
S=pd.Series(np.random.normal(size=200))
S[~((S-S.mean()).abs()>3*S.std())]
#------------------------------------------------------------------------------
# accept a dataframe, remove outliers, return cleaned data in a new dataframe
# see http://www.itl.nist.gov/div898/handbook/prc/section1/prc16.htm
#------------------------------------------------------------------------------
def remove_outlier(df_in, col_name):
q1 = df_in[col_name].quantile(0.25)
q3 = df_in[col_name].quantile(0.75)
iqr = q3-q1 #Interquartile range
fence_low = q1-1.5*iqr
fence_high = q3+1.5*iqr
df_out = df_in.loc[(df_in[col_name] > fence_low) & (df_in[col_name] < fence_high)]
return df_out