পান্ডাস ডেটা ফ্রেমে আউটলিয়ারগুলি সনাক্ত করুন এবং বাদ দিন


196

আমার কাছে কয়েকটি কলাম সহ একটি পান্ডাস ডেটা ফ্রেম রয়েছে।

এখন আমি জানি যে নির্দিষ্ট সারিগুলি একটি নির্দিষ্ট কলাম মানের উপর ভিত্তি করে outliers হয়।

এই ক্ষেত্রে

কলাম 'ভোল' এর চারপাশে সমস্ত মান রয়েছে 12xxএবং একটি মান 4000(আউটলেট)।

এখন আমি সেই সারিগুলি বাদ দিতে চাই যেগুলির Volকলাম রয়েছে।

সুতরাং, মূলত আমাকে ডেটা ফ্রেমে এমন একটি ফিল্টার লাগানো দরকার যাতে আমরা সমস্ত সারি নির্বাচন করি যেখানে নির্দিষ্ট কলামের মানগুলি বোঝায়, বলুন, গড় থেকে 3 টি স্ট্যান্ডার্ড বিচ্যুতি।

এটি অর্জনের একটি মার্জিত উপায় কী?

উত্তর:


213

আপনার যদি আপনার ডেটাফ্রেমে একাধিক কলাম থাকে এবং কমপক্ষে একটি কলামে অপ্রদর্শক রয়েছে এমন সমস্ত সারি মুছে ফেলতে চান, তবে নীচের অভিব্যক্তিটি একটি শটে এটি করবে।

df = pd.DataFrame(np.random.randn(100, 3))

from scipy import stats
df[(np.abs(stats.zscore(df)) < 3).all(axis=1)]

বিবরণ:

  • প্রতিটি কলামের জন্য, প্রথমে এটি কলামের প্রতিটি মানের জেড-স্কোরকে গণনা করে, কলামটির গড় এবং মানক বিচ্যুতি সম্পর্কিত।
  • তারপরে জেড-স্কোরের নিখরচায় লাগে কারণ দিকটি যদি দ্বারপ্রান্তের নীচে থাকে তবে কিছুই যায় আসে না।
  • সমস্ত (অক্ষ = 1) নিশ্চিত করে যে প্রতিটি সারির জন্য, সমস্ত কলাম সীমাবদ্ধতা মেটায়।
  • শেষ অবধি, এই শর্তের ফলাফল ডেটাফ্রেমকে সূচীকরণের জন্য ব্যবহৃত হয়।

6
এই কোডটি কী করছে তা আপনি ব্যাখ্যা করতে পারেন? এবং সম্ভবত একটি ধারণা সরবরাহ করুন যে আমি কীভাবে একটি নির্দিষ্ট নির্দিষ্ট কলামে আউটলেটরযুক্ত সমস্ত সারি সরিয়ে ফেলতে পারি? সহায়ক হবে। ধন্যবাদ।
সাম্যাথ্র্যাব্রেন্ড

17
প্রতিটি কলামের জন্য, প্রথমে এটি কলামের প্রতিটি মানের জেড-স্কোরকে গণনা করে, কলামটির গড় এবং মানক বিচ্যুতি সম্পর্কিত। তারপরে জেড-স্কোরের নিখরচায় লাগে কারণ দিকটি যদি দ্বারপ্রান্তের নীচে থাকে তবে কিছুই যায় আসে না। .all (অক্ষ = 1) প্রতিটি সারিটির জন্য সমস্ত কলাম সীমাবদ্ধতা পূরণ করে তা নিশ্চিত করে। শেষ অবধি, এই শর্তের ফলাফল ডেটাফ্রেমকে সূচীকরণের জন্য ব্যবহৃত হয়।
রাফেলওয়ালে

4
কলামগুলিতে নাল / ন্যান থাকলে আপনি পরিস্থিতিটি কীভাবে পরিচালনা করবেন। কীভাবে আমরা তাদের উপেক্ষা করতে পারি?
অসিমো

6
এই সমাধানের জন্য আমরা কীভাবে স্ট্রিং কলামগুলি ব্যবহার করব? কিছু কলাম যদি অ-সংখ্যাসূচক হয় এবং আমরা সমস্ত সংখ্যার কলামের উপর ভিত্তি করে বিদেশী অপসারণ করতে চাই।
এসএসপি

6
ত্রুটি পেয়েছে: "TypeError: / str 'এবং' int 'এর জন্য অসমর্থিত অপারেন্ড টাইপ (গুলি)
সাক

142

booleanআপনি যেমন করতেন তেমন সূচিকাগুলি ব্যবহার করুন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

একটি সিরিজের জন্য এটি অনুরূপ:

S = pd.Series(np.random.normal(size=200))
S[~((S-S.mean()).abs() > 3*S.std())]

6
DataFrame.abs()এগুলি একটি এফওয়াইআই, এছাড়াওDataFrame.clip()
জেফ

7
clip()জেফের ক্ষেত্রে রূপরেখা সরানো হয়নি: df.SOME_DATA.clip(-3std,+3std)বহিরাগতকে 3 + তম অথবা -3 ষ্ঠ বা
সিটি ঝু

1
এটি প্রায় একই, @ এএমএম
সিটি ঝু

1
যদি আমাদের পান্ডাস ডেটা ফ্রেমের 100 টি কলাম থাকে তবে আমরা কীভাবে একই জিনিস করতে পারি?
ড্রিমারপিপি

1
দুর্দান্ত, উত্তরটির জন্য ধন্যবাদ @ সিটিজেডু। @DreamerP আপনি শুধু দিয়ে পুরো DataFrame এটি প্রয়োগ করতে পারেন: df_new = df[np.abs(df - df.mean()) <= (3 * df.std())]তবে এটি কোনও সিরিজ বা একক কলামে প্রয়োগ করার বিপরীতে np.nan, এটি আউটলিয়ারদের প্রতিস্থাপন করবে এবং ডেটাফ্রেমের আকৃতি রাখবে, সুতরাং অনুপস্থিত মানগুলি পূরণ করার জন্য অন্তরঙ্গকরণের প্রয়োজন হতে পারে।
স্কটি 1-

93

আপনার প্রতিটি ডাটাফ্রেম কলামের জন্য আপনি এর সাথে কোয়ান্টাইল পেতে পারেন:

q = df["col"].quantile(0.99)

এবং তারপরে ফিল্টার করুন:

df[df["col"] < q]

যদি নিম্ন এবং উচ্চতর বহিরাগতদের অপসারণের প্রয়োজন হয় তবে শর্তটি একটি এবং বিবৃতিতে মিশ্রিত করুন:

q_low = df["col"].quantile(0.01)
q_hi  = df["col"].quantile(0.99)

df_filtered = df[(df["col"] < q_hi) & (df["col"] > q_low)]

3
এই নিবন্ধটি আউটলিয়ার অপসারণ কৌশল একটি খুব ভাল ওভারভিউ দেয় machinelearningmastery.com/...
user6903745

2
এটি কেবল ওপরের বাউন্ড থেকে আউটলিয়ারগুলি সরিয়ে ফেলতে পারে .. কম নয়?
indolentdeveloper

1
@indolentdeveloper আপনি ঠিকই বলেছেন, নীচের বহিরাগতদের অপসারণ করতে অসমতার বিপরীত করুন, বা একটি ওআর অপারেটরের সাথে তাদের একত্র করুন।
ব্যবহারকারী 6903745

4
মন্তব্যের ধারণাটি উত্তরগুলি আপডেট করা ছিল;)। যেহেতু কেউ এই পয়েন্টটি মিস করতে পারে।
indolentdeveloper

@ user6903745 এবং বিবৃতি বা "বা"?
এবি

38

এই উত্তরটি @ টানেমাকির সরবরাহিত সমান, তবে lambdaপরিবর্তে একটি অভিব্যক্তি ব্যবহার করে 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)]

ডেটাফ্রেম ফিল্টার করতে যেখানে কেবলমাত্র একটি কলাম (যেমন 'বি') তিনটি স্ট্যান্ডার্ড বিচ্যুতির মধ্যে রয়েছে:

df[((df.B - df.B.mean()) / df.B.std()).abs() < 3]

ঘূর্ণায়মান ভিত্তিতে এই জেড-স্কোরটি কীভাবে প্রয়োগ করবেন তা এখানে দেখুন: পান্ডাস ডেটাফ্রেমে রোলিং জেড-স্কোর প্রয়োগ করা হয়েছে


22
#------------------------------------------------------------------------------
# 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

আমি ত্রুটি পাচ্ছি "ভ্যালুএররার: বহুমাত্রিক কী দিয়ে" সূচী করতে পারছি না "লাইনে" df_out = df_in.loc [(ডিএফ_ইন [কল_নেস]> বেড়া_লো) এবং (ডিএফ_ইন [কল_নাম] <বেড়া_উত্তর)] "আপনি কি সহায়তা করবেন
ইমরান আহমদ গাজালী

18

Dataframe প্রতিটি সিরিজের জন্য, আপনি ব্যবহার করতে পারে betweenএবং quantileoutliers মুছে ফেলার জন্য।

x = pd.Series(np.random.normal(size=200)) # with outliers
x = x[x.between(x.quantile(.25), x.quantile(.75))] # without outliers

3
এখানে আপনি আন্তঃখণ্ডজ রেঞ্জের (আইকিউআর) মধ্যে কেবলমাত্র ডেটা নির্বাচন করছেন, তবে মনে রাখবেন যে এই সীমার বাইরে মান রয়েছে যা বিদেশী নয়।
বিসিএআরগ

2
উদাহরণস্বরূপ 0.1 এবং 0.9 নির্বাচন করা আমার মনে হয় বেশ নিরাপদ হবে। এর মধ্যে এবং কোয়ান্টাইলগুলির মধ্যে ব্যবহার করা একটি দুর্দান্ত বাক্য গঠন।
পাসক্যালভিকুটেন

17

যেহেতু আমি এমন কোনও উত্তর দেখিনি যা সংখ্যাসূচক এবং অ-সংখ্যাসূচক আচরণ করে গুণাবলী নিয়ে কাজ করে, তাই এখানে একটি পরিপূরক উত্তর।

আপনি কেবলমাত্র সংখ্যার বৈশিষ্ট্যগুলিতে আউটলিয়ারগুলি ফেলে দিতে চাইতে পারেন (শ্রেণিবদ্ধ ভেরিয়েবলগুলি খুব কমই আউটলিয়ার হতে পারে)।

ফাংশন সংজ্ঞা

অ-সংখ্যাসূচক বৈশিষ্ট্য উপস্থিত থাকলে আমি ডেটা হ্যান্ডেল করার জন্য @ টানেমাকির পরামর্শ বাড়িয়েছি:

from scipy import stats

def drop_numerical_outliers(df, z_thresh=3):
    # Constrains will contain `True` or `False` depending on if it is a value below the threshold.
    constrains = df.select_dtypes(include=[np.number]) \
        .apply(lambda x: np.abs(stats.zscore(x)) < z_thresh, reduce=False) \
        .all(axis=1)
    # Drop (inplace) values set to be rejected
    df.drop(df.index[~constrains], inplace=True)

ব্যবহার

drop_numerical_outliers(df)

উদাহরণ

dfবাড়িগুলি সম্পর্কে কিছু মান সহ একটি ডেটাসেটের কল্পনা করুন : অ্যালি, জমির কনট্যুর, বিক্রয় মূল্য, ... উদাহরণস্বরূপ: ডেটা ডকুমেন্টেশন

প্রথমত, আপনি একটি স্ক্যাটার গ্রাফে ডেটা ভিজ্যুয়ালাইজ করতে চান (জেড-স্কোর ত্রিশ = 3 সহ):

# Plot data before dropping those greater than z-score 3. 
# The scatterAreaVsPrice function's definition has been removed for readability's sake.
scatterAreaVsPrice(df)

এর আগে - জিআর লিভ এরিয়া ভার্সেস সেলস প্রাইস

# Drop the outliers on every attributes
drop_numerical_outliers(train_df)

# Plot the result. All outliers were dropped. Note that the red points are not
# the same outliers from the first plot, but the new computed outliers based on the new data-frame.
scatterAreaVsPrice(train_df)

এর পরে - জিআর লিভ এরিয়া ভার্সেস সেলস প্রাইস


2
দুর্দান্ত সমাধান! হিসাবে শীর্ষস্থানীয় সংস্করণ 0.23.0 reduce=Falseথেকে pandasঅবহিত করা হয়েছে
কে 1

সাবস্টিটিউট result_type='reduce'জন্য reduce=False
একাবা বিসং

8

scipy.statsর‍্যাঙ্কিং এবং অপসৃত মানগুলির একটি প্রবর্তিত শতাংশ অনুসারে পদ্ধতি রয়েছে trim1()এবং trimboth()একক সারিতে আউটলিরদের কাটাতে।


1
trimbothআমার জন্য সবচেয়ে সহজ ছিল।
শব্দসুবিহীন

6

আরেকটি বিকল্প হ'ল আপনার ডেটা রুপান্তর করা যাতে বহিরাগতদের প্রভাব হ্রাস পায়। আপনি আপনার ডেটা বিজয়ী করে এটি করতে পারেন।

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()

উইনসরাইজড ডেটা


6

আপনি যদি পদ্ধতিতে শৃঙ্খলা পছন্দ করেন তবে আপনি এই জাতীয় সংখ্যার কলামগুলির মতো আপনার বুলিয়ান শর্তটি পেতে পারেন:

df.sub(df.mean()).div(df.std()).abs().lt(3)

প্রতিটি কলামের প্রতিটি মান এর True/Falseচেয়ে তিনটি মানের বিচ্যুতির গড় থেকে দূরে রয়েছে কিনা তার ভিত্তিতে রূপান্তরিত হবে ।


le(3)এটির অপসারণকারীদের অপসারণের পরে এটি হওয়া উচিত । এইভাবে আপনি Trueপ্রবাসীদের জন্য পাবেন get এর বাইরে +1 এবং এই উত্তরটি উচ্চতর হওয়া উচিত
এরফান

2

আপনি বুলিয়ান মাস্ক ব্যবহার করতে পারেন:

import pandas as pd

def remove_outliers(df, q=0.05):
    upper = df.quantile(1-q)
    lower = df.quantile(q)
    mask = (df < upper) & (df > lower)
    return mask

t = pd.DataFrame({'train': [1,1,2,3,4,5,6,7,8,9,9],
                  'y': [1,0,0,1,1,0,0,1,1,1,0]})

mask = remove_outliers(t['train'], 0.1)

print(t[mask])

আউটপুট:

   train  y
2      2  0
3      3  1
4      4  1
5      5  0
6      6  0
7      7  1
8      8  1

1

যেহেতু আমি আমার ডেটা বিজ্ঞান যাত্রার খুব প্রাথমিক পর্যায়ে আছি, তাই আমি নীচের কোড দিয়ে বহিরাগতদের চিকিত্সা করছি।

#Outlier Treatment

def outlier_detect(df):
    for i in df.describe().columns:
        Q1=df.describe().at['25%',i]
        Q3=df.describe().at['75%',i]
        IQR=Q3 - Q1
        LTV=Q1 - 1.5 * IQR
        UTV=Q3 + 1.5 * IQR
        x=np.array(df[i])
        p=[]
        for j in x:
            if j < LTV or j>UTV:
                p.append(df[i].median())
            else:
                p.append(j)
        df[i]=p
    return df

1

আমাদের আগতদের সীমা হিসাবে 98 তম এবং 2 য় পার্সেন্টাইল পান

upper_limit = np.percentile(X_train.logerror.values, 98) 
lower_limit = np.percentile(X_train.logerror.values, 2) # Filter the outliers from the dataframe
data[‘target’].loc[X_train[‘target’]>upper_limit] = upper_limit data[‘target’].loc[X_train[‘target’]<lower_limit] = lower_limit

0

ডেটা এবং ২ টি গোষ্ঠী সহ একটি পূর্ণ উদাহরণ:

আমদানি:

from StringIO import StringIO
import pandas as pd
#pandas config
pd.set_option('display.max_rows', 20)

2 টি গ্রুপের সাথে ডেটা উদাহরণ: জি 1: গ্রুপ 1. জি 2: গ্রুপ 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
""")

পান্ডাস ডেটাফ্রেমে পাঠ্য ডেটা পড়ুন:

df = pd.read_csv(TESTDATA, sep=";")

স্ট্যান্ডার্ড বিচ্যুতি ব্যবহার করে আউটলিয়ারগুলি সংজ্ঞায়িত করুন

stds = 1.0
outliers = df[['G1', 'G2', 'Value']].groupby(['G1','G2']).transform(
           lambda group: (group - group.mean()).abs().div(group.std())) > stds

ফিল্টার করা ডেটা মান এবং আউটলিয়ারগুলি সংজ্ঞায়িত করুন:

dfv = df[outliers.Value == False]
dfo = df[outliers.Value == True]

ফলাফল মুদ্রণ করুন:

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)

0

আউটলিয়ারদের বাদ দেওয়ার জন্য আমার কাজ

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)

0

আমি ড্রপ চেয়ে ক্লিপ পছন্দ। নিম্নলিখিতটি দ্বিতীয় এবং 98 তম পেনসিলগুলিতে স্থানটি ক্লিপ করবে।

df_list = list(df)
minPercentile = 0.02
maxPercentile = 0.98

for _ in range(numCols):
    df[df_list[_]] = df[df_list[_]].clip((df[df_list[_]].quantile(minPercentile)),(df[df_list[_]].quantile(maxPercentile)))

-2

আউটলিয়ারগুলি মোছা এবং ফেলে দেওয়া আমার বিশ্বাস পরিসংখ্যানগত দিক থেকে ভুল। এটি ডেটাটিকে মূল তথ্য থেকে আলাদা করে তোলে। এছাড়াও ডেটাটিকে অসম আকারযুক্ত করে তোলে এবং তাই লগের মাধ্যমে ডেটা ট্রান্সফর্মের মাধ্যমে বহিরাগতদের প্রভাব হ্রাস করা বা এড়ানো ভাল উপায়। এটি আমার পক্ষে কাজ করেছে:

np.log(data.iloc[:, :])

3
ওপি কেন কিছু করতে চায় সে সম্পর্কে অনুমান করা যায় না।
রাজেশএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.