راهنمای جامع تکنیک های مواجهه با  Null یا Missing Value ها

در این پست سعی میکنم به طور مختصر و مفید، بگم که اولا چطور "تمامی" داده های Null رو در دیتاست مون پیدا کنیم و ثانیا "تکنیک" های مواجهه باهاشون رو به طور عملیاتی معرفی می کنم.بدون شرح:))1- یافتن مقادیر Null:قبل از هر چیز بریم سراغ اینکه ببینیم آیا دیتاست ما دارای مقدار null هست یا خیر. و اگر بله در کدام ستون ها. برای اینکار از کد زیر استفاده می کنیم:dataframe_name.isnull().sum()مثلا با استفاده از این کد برای دیتاست Titanic داریم:داده های null در دیتاست Titanic 2- نحوه Dealکردن با داده های Null:خب تا به اینجا دیدیم که چطور "تمامی" داده های Null رو پیدا کنیم. در این مرحله میخوایم ببینیم چطور باید در Preprocess داده ها، با این مقادیر برخورد کنیم تا در مدلسازی به مشکل برنخوریم. "شش" راهکار کلی برای مواجهه با این نوع داده ها وجود دارد:1-حذف ردیف هایی دارای مقادیر Null: راحت ترین روش برای مواجهه با مقادیر null، حذف آنهاست. اما تنها زمانی استفاده از این روش پیشنهاد می شود که اولا با حذف ردیف های دارای مقدار null میزان دادهء باقی مانده برای مدلسازی و پیش بینی کافی باشد و ثانیا ردیف های دارای مقادیر null نماینده اعضای خاصی از دیتاست ما نباشند. یعنی چی؟مثلا فرض کنید میخواهید از یک دیتاست برای Classification استفاده کنید. متغیر وابسته یا کلاس های شما دارای دو حالتِ "سالم" و "بیمار" هستند. اگر تمامی ردیف هایی که نمایندهء کلاسِ بیمار هستند دارای مقدار null باشند، با حذف مقادیر null، کل داده های مربوط به یک کلاس مان را از دست می دهیم و بنابراین نخواهیم توانست به درستی داده ها را مدل نماییم. پس در استفاده از این روش باید حواسمان باشد که به کاهش شدید دیتا درمورد بخشی از جامعهء بررسی شده در دیتاست منجر نشود.در کل طبق تجربه یک قانون سرانگشتی(rule of thumb) برای اینکه ببینیم میتونیم از این روش استفاده کنیم یا نه این هست که ببینیم اولا تعداد ردیف های دارای داده های null کمتر از 10-20% کل ردیف ها در دیتاست باشد، ثانیا با حذف این ردیف ها، تعداد سمپل ها(ردیف) برای مدلسازی کافی باشد.خب حالا چطور این کار را انجام دهیم؟ شما می توانید از دستور زیر برای حذف ردیف هایی با مقدار null استفاده نمایید:dataframe_name= dataframe_name.dropna()نکته اینکه حتما حواستان باشد همانند بالا، خروجی dropna را مجدد به دیتافریم تون مقداردهی نمایید و الا مقادیر null از دیتافریم حذف نمی شوند.2-استفاده از ffill و bfill: با استنفاده از دستورات ffill و bfill می توان به ترتیب مقدار ردیف قبلی و ردیف بعدی در یک ستون را به سلولِ دارای مقدار null داد. مزیت این روش سرعت و سادگی آن است اما دقت را قربانی می کند، چرا که مقادیر دو ردیف متوالی می توانند بسیار متفاوت باشند. نتیجه اینکه اگر ساخت مدلی با دقت بالا برایتان در اولویت است، توصیه میکنم از این روش استفاده نکنید مگر اینکه از نزدیک بودن مقادیر یک فیچر(متغیر مستقل) برای تمامی سمپل ها اطلاع داشته باشید.برای استفاده از این روش می توانید از کد زیر برنامهء خود استفاده نمایید:dataframe_name['column_name'].ffill()dataframe_name['column_name'].bfill()در کد بالا، column_name نشان دهنده نام ستونی است که به دنبال حذف مقادیر null از آن هستیم.دقت کنید که "ffill" برای پر کردن سلول null با استفاده از مقدار سلول "قبلی" و "bfill" برای پر کردن سلول null با استفاده از مقدار سلول "بعدی" استفاده می شود.3-استفاده از مقادیر عددی ثابت: درصورتیکه که یک insight ( بینش یا پیش بینی) دررابطه با مقادیر ممکن برای یک ستون داشته باشیم، می توانیم از این مقدار برای جایگزینی null استفاده کنیم. برای این کار می توانیم از کد زیر استفاده کنیم:dataframe_name['column_name'].fillna(value)در کد بالا به جای مقدار value می توانیم از مقدار مدنظرمون استفاده کنیم.4- استفاده از میانگین ستون: این روش به نسبت روش دقیقتری از روش های قبلی است. در این روش از میانگین مقادیرِ موجود برای یک ستون برای جایگزینی مقادیر از دست رفته استفاده می کنیم. برای این کار از کد زیر استفاده می نماییم:dataframe_name['column_name'].fillna( dataframe_name['column_name'].mean() , inplace=True)درواقع به جای جایگذاری مقدار value، در راهکار قبلی، اینجا از مقدار میانگین(mean) داده ها استفاده می کنیم.5- استفاده از میانگین هم گروه در یک ستون: این روش دقیقتر از روش قبلی است. به این شکل است که ابتدا سمپل های مشابه در دیتاست را در یک گروه قرار می دهیم، سپس به جای استفاده از میانگین کل داده های یک ستون برای جایگزینی مقدار null، از میانگین داده های هم گروه(مشابه) یک سلول استفاده می کنیم. برای پیاده سازی این روش داریم:dataframe_name['columnC'].fillna( dataframe_name.groupby([columnA] , [columnB])["columnC"].transform('mean') )به عنوان مثال برای دیتاست تایتانیک داریم:titanic['age'].fillna(titanic.groupby(['pclass', 'alone'])['age'].transform('mean'))خب کد بالا دقیقا چی داره میگه؟ به مقادیر داخل پرانتزِ fillna نگاه کنید. اول میاد دیتاست رو بر اساس ستون های alone و pclass گروه بندی می کنه. اینجا از دو ستون استفاده شده، شما میتونید از هر چندتا ستون در این قسمت استفاده کنید. باید نام ستون هایی که میخواید گروه بندی بر اساس مقادیر اونها صورت بگیره رو در اینجا بنویسید. بعد از اینکه گروه بندی میکنه میگه حالا ستون age از این دیتاستِ گروه بندی شده رو پیدا کن، بعد مقدار میانگین گروهش رو بهش پس بده. اینطوری مقادیر null با مقادیرِ میانگین هم گروهی شون جایگزین میشن.اما تکنیک آخر که دقیقترین و بهترین روش هست:6- استفاده از Iterative Imputerها: حتما با رگرسیون آشنایی دارید. با استفاده از مدلهای رگرسیون ما میتونیم مقادیر متغیر وابسته رو در یک دیتاست بدست بیاریم. خب چرا از این روش برای پیدا کردن مقادیر null در دیتاست استفاده نکنیم؟ :) این روش میاد ردیف های دارای مقدار null رو به عنوان ورودی میگیره، بعد میاد بر اساس سایر سلول های ردیف که مقدارشون موجود هست و استفاده از اطلاعات ردیف هایی که کامل و بدون مقدار null هستند، یک رگرسیون run میکنه و مقدار null در یک ردیف رو پیش بینی میکنه. به همین خاطر دقیقترین روش در بین روش های مواجهه با null هست. چطور از این روش استفاده کنیم؟ شما میتونید از کد زیر استفاده کنید:from sklearn.experimental import enable_iterative_imputerfrom sklearn.impute import IterativeImputerfrom sklearn.ensemble import RandomForestRegressorbuild_imputer=IterativeImputer(estimator=RandomForestRegressor(n_estimators= 100))dataframe_name=build_imputer.fit_transform(dataframe_name)چند نکته رو به خاطر داشته باشید: من در اینجا از روش Random Forest برای رگرسیون و یافتن مقادیر null استفاده کردم. می توان از روش های دیگر رگرسیون استفاده کرد. اما طبق تجربه این روش بهترین جواب رو بهتون میده.پس از استفاده از imputer دیتاست تون به یک nparray تبدیل میشه. پس اگر میخواید یک Pandas dataframe داشته باشید باید اون رو از طریق کد زیر تبدیل کنید:dataframe_name=pd.DataFrame(dataframe_name , columns=['A', 'B', 'C'])نتیجه گیری:در این مقاله با 6 تکنیک اصلی مواجهه با مقادیر null در دیتاست و نحوهء پیاده سازی آنها آشنا شدیم. شما می توانید تکنیک های متفاوتی را برای مواجهه با مقادیر null در ستون های جداگانه انتخاب کنید. بهترین و دقیقترین روش استفاده از Iterative Imputer هست که مقادیر null را با دقیقترین مقدار برای آنها جایگزین می کند.در این مقاله سعی کردم تکنیک های اصلی رو بدون شاخ و برگ دادن و به طور ساده و عملیاتی براتون بیان کنم. امیدوارم از این مقاله استفاده کرده باشید، اگر علاقه مند به مطالعه بیشتر در زمینه Data Science و AI هستید میتونید صفحه من رو فالو کنید: virgool.io/@fvyounesiاگر سوالی هست بنویسید، پاسخگو هستم.