পান্ডাস ডেটা ফ্রেমে কাস্টম বাছাই


93

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

আমি অভিধান ব্যবহার করে কীভাবে একটি কাস্টম বাছাই করতে পারি, উদাহরণস্বরূপ:

custom_dict = {'March':0, 'April':1, 'Dec':3}  

4
কোনও কলামে মাসের নামের অর্থ কী এমন কোনও কলাম রয়েছে যার মধ্যে মাসের নাম রয়েছে (আমার উত্তর হিসাবে), বা কলামের সাথে অনেকগুলি কলামের নাম যেমন মাসের নাম রয়েছে (ইউমিরো হিসাবে)?
অ্যান্ডি হেডেন

4
গৃহীত উত্তরটি পুরানো, এবং প্রযুক্তিগতভাবেও ভুল, কারণ pd.Categoricalডিফল্টরূপে আদেশ অনুসারে বিভাগগুলি ব্যাখ্যা করে না। এই উত্তর দেখুন ।
সিএস 95

উত্তর:


148

পান্ডাস 0.15 শ্রেণীবদ্ধ সিরিজ চালু করেছে , যা এটি করার জন্য আরও স্পষ্টভাবে অনুমতি দেয়:

প্রথমে মাসের কলামটিকে একটি শ্রেণিবদ্ধ করুন এবং ব্যবহারের ক্রমটি নির্দিষ্ট করুন।

In [21]: df['m'] = pd.Categorical(df['m'], ["March", "April", "Dec"])

In [22]: df  # looks the same!
Out[22]:
   a  b      m
0  1  2  March
1  5  6    Dec
2  3  4  April

এখন, আপনি যখন মাসের কলামটি বাছাই করবেন তখন সেই তালিকার সাথে এটি সাজবে:

In [23]: df.sort_values("m")
Out[23]:
   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

দ্রষ্টব্য: তালিকায় যদি কোনও মান না থাকে তবে এটি NaN এ রূপান্তরিত হবে।


আগ্রহীদের জন্য একটি পুরানো উত্তর ...

আপনি একটি মধ্যস্থতাকারী সিরিজ তৈরি করতে পারেন এবং তার set_indexউপর:

df = pd.DataFrame([[1, 2, 'March'],[5, 6, 'Dec'],[3, 4, 'April']], columns=['a','b','m'])
s = df['m'].apply(lambda x: {'March':0, 'April':1, 'Dec':3}[x])
s.sort_values()

In [4]: df.set_index(s.index).sort()
Out[4]: 
   a  b      m
0  1  2  March
1  3  4  April
2  5  6    Dec

যেমনটি মন্তব্য করা হয়েছে, নতুন পান্ডায় সিরিজের আরও সুদৃantly়ভাবে এটি করার একটি replaceপদ্ধতি রয়েছে :

s = df['m'].replace({'March':0, 'April':1, 'Dec':3})

সামান্য পার্থক্য হ'ল অভিধানের বাইরের কোনও মান থাকলে এটি উত্থিত হবে না (এটি কেবল একই থাকবে)।


s = df['m'].replace({'March':0, 'April':1, 'Dec':3})লাইন 2 পাশাপাশি কাজ করে - কেবল আমার মতো পান্ডা শেখার জন্যই
kdauria

@ কেডৌরিয়া ভাল জায়গা! (আমি এটি লেখার পরে একটি সময় হয়ে গেছে!) অবশ্যই সর্বোত্তম বিকল্পটি প্রতিস্থাপন করুন, অন্যটি ব্যবহার করা হবে .apply({'March':0, 'April':1, 'Dec':3}.get):) ০.৫৫ তে আমাদের কাছে শ্রেণিবদ্ধ সিরিজ / কলাম থাকবে, তাই সর্বোত্তম উপায়টি এটি ব্যবহার করা এবং তারপরে সাজানো ঠিক কাজ করবে।
অ্যান্ডি হেডেন 19

@ অ্যান্ডি হেডেন আমি দ্বিতীয় প্রতিভাটিকে 'প্রতিস্থাপন' পদ্ধতিতে প্রতিস্থাপনের স্বাধীনতা নিয়েছি। আমি আশা করি ঠিক আছে।
ফাহিম মিঠা

@ অ্যান্ডি হেডেন সম্পাদনা প্রত্যাখ্যান করা হয়েছে, তবে আমি এখনও মনে করি এটি একটি যুক্তিসঙ্গত পরিবর্তন।
ফাহিম মিঠা

7
কেবলমাত্র নিশ্চিত হয়ে নিন যে আপনি df.sort_values("m")নতুন পান্ডায় ব্যবহার করেছেন (পরিবর্তে df.sort("m")), অন্যথায় আপনি একটি পাবেন AttributeError: 'DataFrame' object has no attribute 'sort';)
বুদ্ধিমত্তা

21

পান্ডাস> = 1.1

আপনি শীঘ্রই যুক্তি sort_valuesদিয়ে ব্যবহার করতে সক্ষম হবেন key:

pd.__version__
# '1.1.0.dev0+2004.g8d10bfb6f'

custom_dict = {'March': 0, 'April': 1, 'Dec': 3} 
df

   a  b      m
0  1  2  March
1  5  6    Dec
2  3  4  April

df.sort_values(by=['m'], key=lambda x: x.map(custom_dict))

   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

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


পান্ডাস <= 1.0.X

এক সহজ পদ্ধতি আউটপুট ব্যবহার করছে Series.mapএবং Series.argsortমধ্যে সূচক dfব্যবহার DataFrame.iloc(যেহেতু argsort সাজানো পূর্ণসংখ্যা অবস্থানের উত্পাদন করে); যেহেতু আপনার একটি অভিধান রয়েছে; এটি সহজ হয়ে যায়।

df.iloc[df['m'].map(custom_dict).argsort()]

   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

যদি আপনাকে অবতরণ ক্রম অনুসারে বাছাই করা দরকার , ম্যাপিংটি উল্টে দিন।

df.iloc[(-df['m'].map(custom_dict)).argsort()]

   a  b      m
1  5  6    Dec
2  3  4  April
0  1  2  March

দ্রষ্টব্য যে এটি কেবল সংখ্যাযুক্ত আইটেমগুলিতে কাজ করে। অন্যথায়, আপনাকে এটি ব্যবহার sort_valuesকরে সূচকটি অ্যাক্সেস করতে হবে:

df.loc[df['m'].map(custom_dict).sort_values(ascending=False).index]

   a  b      m
1  5  6    Dec
2  3  4  April
0  1  2  March

এর সাথে আরও বিকল্প উপলব্ধ astype(এটি এখন হ্রাস করা হয়), বা pd.Categorical, তবে ordered=Trueএটি সঠিকভাবে কাজ করার জন্য আপনাকে নির্দিষ্ট করতে হবে

# Older version,
# df['m'].astype('category', 
#                categories=sorted(custom_dict, key=custom_dict.get), 
#                ordered=True)
df['m'] = pd.Categorical(df['m'], 
                         categories=sorted(custom_dict, key=custom_dict.get), 
                         ordered=True)

এখন, একটি সাধারণ sort_valuesকলটি কৌশলটি করবে:

df.sort_values('m')
 
   a  b      m
0  1  2  March
2  3  4  April
1  5  6    Dec

groupbyআউটপুট বাছাই করার সময় বিভাগীয় ক্রমও সম্মানিত হবে ।


4
আপনি ইতিমধ্যে এটির উপর জোর দিয়ে গেছেন, তবে অন্য কেউ এটিকে স্কিম করে এবং মিস করতে না পারে সে ক্ষেত্রে আমি আবারও বলতে চাই: ordered=Noneডিফল্টরূপে পান্ডাস শ্রেণিবদ্ধ সেট । যদি সেট না করা থাকে তবে অর্ডারিংটি ভুল হবে, বা ভি 23 এ ব্রেক হবে। বিশেষত সর্বাধিক ফাংশন একটি টাইপরর দেয় (শ্রেণিবদ্ধের অপারেশন সর্বাধিকের জন্য আদেশ করা হয় না)।
ডেভ লিউ

17

হালনাগাদ

নির্বাচিত উত্তর ব্যবহার করুন ! এটি এই পোস্টের চেয়েও নতুন এবং প্যান্ডাসে অর্ডার করা ডেটা বজায় রাখার আনুষ্ঠানিক উপায় নয়, বৈশিষ্ট্য / কর্মক্ষমতা ইত্যাদিসহ প্রতিটি ক্ষেত্রেই এটি আরও ভাল etc. আমি নীচে বর্ণিত আমার হ্যাকি পদ্ধতিটি ব্যবহার করবেন না।

আমি কেবল এই আপডেটটি লিখছি কারণ লোকেরা আমার উত্তরকে সমর্থন করে চলেছে তবে এটি অবশ্যই গ্রহণযোগ্যটির চেয়ে খারাপ worse

আসল পোস্ট

গেমটি থেকে কিছুটা দেরীতে, তবে এখানে এমন একটি ফাংশন তৈরির উপায় যা স্বেচ্ছাসেবী ফাংশনগুলি ব্যবহার করে পান্ডাস সিরিজ, ডেটাফ্রেম এবং মাল্টিইন্ডেক্স ডেটাফ্রেম অবজেক্টগুলিকে সাজিয়ে তোলে।

আমি সেই df.iloc[index]পদ্ধতিটি ব্যবহার করি , যা অবস্থান অনুসারে সিরিজ / ডেটাফ্রেমের একটি সারি উল্লেখ করে (তুলনায় df.loc, কোনটি মান অনুসারে রেফারেন্স করে)। এটি ব্যবহার করে, আমাদের কেবল একটি ফাংশন থাকতে হবে যা অবস্থানগত আর্গুমেন্টগুলির একটি সিরিজ দেয়:

def sort_pd(key=None,reverse=False,cmp=None):
    def sorter(series):
        series_list = list(series)
        return [series_list.index(i) 
           for i in sorted(series_list,key=key,reverse=reverse,cmp=cmp)]
    return sorter

আপনি কাস্টম বাছাইয়ের ক্রিয়া তৈরি করতে এটি ব্যবহার করতে পারেন। এটি অ্যান্ডি হেডেনের উত্তরে ব্যবহৃত ডেটাফ্রেমে কাজ করে:

df = pd.DataFrame([
    [1, 2, 'March'],
    [5, 6, 'Dec'],
    [3, 4, 'April']], 
  columns=['a','b','m'])

custom_dict = {'March':0, 'April':1, 'Dec':3}
sort_by_custom_dict = sort_pd(key=custom_dict.get)

In [6]: df.iloc[sort_by_custom_dict(df['m'])]
Out[6]:
   a  b  m
0  1  2  March
2  3  4  April
1  5  6  Dec

এটি মাল্টিইন্ডেক্স ডেটা ফ্রেম এবং সিরিজ অবজেক্টগুলিতেও কাজ করে:

months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']

df = pd.DataFrame([
    ['New York','Mar',12714],
    ['New York','Apr',89238],
    ['Atlanta','Jan',8161],
    ['Atlanta','Sep',5885],
  ],columns=['location','month','sales']).set_index(['location','month'])

sort_by_month = sort_pd(key=months.index)

In [10]: df.iloc[sort_by_month(df.index.get_level_values('month'))]
Out[10]:
                 sales
location  month  
Atlanta   Jan    8161
New York  Mar    12714
          Apr    89238
Atlanta   Sep    5885

sort_by_last_digit = sort_pd(key=lambda x: x%10)

In [12]: pd.Series(list(df['sales'])).iloc[sort_by_last_digit(df['sales'])]
Out[12]:
2    8161
0   12714
3    5885
1   89238

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


এটি একাধিক কলাম / সূচি বাছাইয়ের জন্য কাজ করবে?
কনানজি

হ্যাঁ, তবে নির্বাচিত উত্তর এটি করার একটি আরও ভাল উপায়। আপনার যদি একাধিক সূচক থাকে তবে আপনার পছন্দ অনুসারে বাছাই করা ক্রম অনুসারে সেগুলি সাজান, তারপরে df.sort_index()সমস্ত সূচী স্তরগুলি সাজানোর জন্য ব্যবহার করুন ।
মাইকেল দেলগাদো

9
import pandas as pd
custom_dict = {'March':0,'April':1,'Dec':3}

df = pd.DataFrame(...) # with columns April, March, Dec (probably alphabetically)

df = pd.DataFrame(df, columns=sorted(custom_dict, key=custom_dict.get))

মার্চ, এপ্রিল, ডিসেম্বর কলাম সহ একটি ডেটা ফ্রেম প্রদান করে


এটি কলামে কাস্টম প্রিকিকেটের উপর ভিত্তি করে সারিগুলি বাছাই করার পরিবর্তে প্রকৃত কলামগুলি বাছাই করে?
সিএস 95
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.