NaN (অনুপস্থিত) মান সহ পান্ডাস গ্রুপপথে কলামগুলি


147

আমার কলামগুলিতে অনেক হারিয়ে যাওয়া মান সহ একটি ডেটাফ্রেম রয়েছে যা আমি গ্রুপবাই করতে চাই:

import pandas as pd
import numpy as np
df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']})

In [4]: df.groupby('b').groups
Out[4]: {'4': [0], '6': [2]}

দেখুন পান্ডারা NaN টার্গেটের মান সহ সারিগুলি বাদ দিয়েছে। (আমি এই সারিগুলি অন্তর্ভুক্ত করতে চাই!)

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

কোনও পরামর্শ? আমি কি এই জন্য একটি ফাংশন লিখতে হবে বা একটি সহজ সমাধান আছে?


1
@ ফিলিপক্লাউড আমি এই প্রশ্নটি সম্পাদনা করেছি কেবলমাত্র প্রশ্নটি অন্তর্ভুক্ত করতে, যা জেফের খোলা পান্ডাস বর্ধনের সাথে সম্পর্কিত, আসলেই বেশ ভাল ।
অ্যান্ডি হেডেন

1
গ্রুপগুলিতে ন্যানকে অন্তর্ভুক্ত করতে (এবং প্রচার করতে) সক্ষম না হওয়াই যথেষ্ট উদ্বেগজনক। আর এর উদ্ধৃতি বিশ্বাসযোগ্য নয়, কারণ এই আচরণটি অন্যান্য অনেক কিছুর সাথে সামঞ্জস্যপূর্ণ নয়। যাইহোক, ডামি হ্যাকটিও বেশ খারাপ। তবে, কোনও গ্রুপের আকার (নাএএনএস অন্তর্ভুক্ত) এবং এনএএনএস থাকলে একটি গোষ্ঠীর গণনা (এনএএনএস উপেক্ষা করে) আলাদা হবে। dfgrouped = df.groupby (['b'])। a.agg (['যোগফল', 'আকার', 'গণনা']) dfgrouped ['যোগফল'] [dfgrouped ['আকার']! = dfgrouped ['গণনা ']] = কিছুই নেই
ব্রায়ান প্রেসলপস্কি

আপনি বিশেষত যা অর্জন করার চেষ্টা করছেন তা সংক্ষেপে বলতে পারেন? অর্থাৎ আমরা একটি আউটপুট দেখতে পাচ্ছি, তবে "পছন্দসই" আউটপুটটি কী?
সিএ

2
পান্ডাস 1.1 আপনি শীঘ্রই নির্দিষ্ট করতে সক্ষম হবে dropna=Falsegroupby()আপনার কাঙ্ক্ষিত ফলাফল পেতে। আরও তথ্য
cs95

উত্তর:


130

ডক্সের অনুপস্থিত তথ্য বিভাগে এটি উল্লেখ করা হয়েছে :

গ্রুপবি-তে এনএ গ্রুপগুলি স্বয়ংক্রিয়ভাবে বাদ পড়েছে। এই আচরণটি আর এর সাথে সামঞ্জস্যপূর্ণ, উদাহরণস্বরূপ।

একটি কাজ হ'ল গ্রুপবাইয়ের আগে প্লেসোল্ডার ব্যবহার করা (যেমন -1):

In [11]: df.fillna(-1)
Out[11]: 
   a   b
0  1   4
1  2  -1
2  3   6

In [12]: df.fillna(-1).groupby('b').sum()
Out[12]: 
    a
b    
-1  2
4   1
6   3

এটি বলেছিল, এটি বেশ ভয়ঙ্কর হ্যাক অনুভব করছে ... সম্ভবত গ্রুপএনবিতে NaN অন্তর্ভুক্ত করার বিকল্প থাকতে হবে ( এই গিথুব ইস্যুটি দেখুন - যা একই স্থানধারক হ্যাক ব্যবহার করে)।


4
এটি একটি যৌক্তিক তবে এক ধরণের মজার সমাধান যা আমি এর আগে ভেবেছিলাম, পান্ডাস খালিগুলি থেকে NaN ক্ষেত্র তৈরি করে, এবং আমাদের সেগুলি আবার পরিবর্তন করতে হবে। এই কারণেই আমি এসকিউএল সার্ভার চালানো এবং সেখান থেকে টেবিলগুলি জিজ্ঞাসা করা (কিছুটা জটিল বলে মনে হচ্ছে), বা পান্ডাস সত্ত্বেও অন্য একটি গ্রন্থাগার সন্ধান করার জন্য বা আমার নিজস্ব ব্যবহার করার মতো অন্যান্য সমাধানগুলি সন্ধান করার কথা ভাবছি that মুক্তি পেতে). থেক্স
গায়ুলা স্যামুয়েল কারলি

@ গায়ুলাসিউমেলকার্লি আমার কাছে এটি একটি ছোট বাগ বলে মনে হচ্ছে (উপরের বাগেরপোর্টটি দেখুন), এবং আমার সমাধানটি কার্যকারণ। আমি আশ্চর্যজনক মনে করি আপনি পুরো লাইব্রেরিটি লিখে ফেলেন।
অ্যান্ডি হেডেন

1
আমি পান্ডা লিখতে চাই না কেবল সেই সরঞ্জামটির সন্ধান করুন যা আমার অনুরোধগুলির সাথে সবচেয়ে বেশি ফিট করে।
গায়ুলা স্যামুয়েল কারলি

1
নীচে আমার উত্তরটি দেখুন, আমি বিশ্বাস করি যে আমি একটি খুব ভাল (ক্লিনার এবং সম্ভবত দ্রুত) সমাধান পেয়েছি। stackoverflow.com/a/43375020/408853
ca

4
না, এটি আর। ডিএফ%>% %__ এর সাথে সামঞ্জস্যপূর্ণ নয় এমন এনএ সংক্ষিপ্তসারগুলি একটি সতর্কতার সাথে দেবে যা fct_explicit_na এর মাধ্যমে গ্রুপিং কলামটি পাস করে এড়ানো যায় এবং তারপরে একটি (অনুপস্থিত) স্তর তৈরি হয়।
রাভেজিং কেয়ার

40

প্রাচীন বিষয়, যদি কেউ এখনও এ নিয়ে হোঁচট খায় তবে - অন্য একটি কাজটি গ্রুপিংয়ের আগে .astype (str) এর মাধ্যমে স্ট্রিংয়ে রূপান্তর করা। এটি NaN এর সংরক্ষণ করবে।

in:
df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']})
df['b'] = df['b'].astype(str)
df.groupby(['b']).sum()
out:
    a
b   
4   1
6   3
nan 2

@ কে 3 --- আরএনসি: আপনার লিঙ্কটিতে মন্তব্য দেখুন - আপনার লিঙ্কে পোস্টের লেখক কিছু ভুল করেছেন।
টমাস

@ থমাস, হ্যাঁ, ঠিক উপরের উদাহরণে যেমন। আপনি উদাহরণটি নিরাপদ করতে (এবং তুচ্ছ হিসাবে) করতে পারেন দয়া করে সম্পাদনা করুন।
কে 3 --- আরএনসি

sumএর aস্ট্রিং সংযুক্তকরণের এখানে, না একটি সাংখ্যিক পরিধি এ পর্যন্তই। এটি কেবল "কাজ করে" কারণ 'বি' তে স্বতন্ত্র এন্ট্রি রয়েছে। আপনার সংখ্যার হতে 'এ' এবং স্ট্রিং হতে 'বি' দরকার
বলপয়েন্টবেন

28

পান্ডাস> = 1.1

পান্ডাস ১.১ থেকে আপনার এই আচরণের উপর আরও ভাল নিয়ন্ত্রণ রয়েছে, এনএ মানগুলি এখন গ্রুপারে ব্যবহার করে মঞ্জুরিপ্রাপ্তdropna=False :

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

# Example from the docs
df

   a    b  c
0  1  2.0  3
1  1  NaN  4
2  2  1.0  3
3  1  2.0  2

# without NA (the default)
df.groupby('b').sum()

     a  c
b        
1.0  2  3
2.0  2  5
# with NA
df.groupby('b', dropna=False).sum()

     a  c
b        
1.0  2  3
2.0  2  5
NaN  1  4

4
আশা করি এই উত্তরটি ধীরে ধীরে শীর্ষে উঠবে। এটি সঠিক পন্থা।
kdbanman

আমি মনে করি না যে 1.1 প্রকাশিত হয়েছে এখনও। কনডা এবং পাইপ এবং চেক করা সংস্করণগুলিতে এখনও আছে 1.0.4
সামিওয়েমি

1
@ সাম্মিওয়েমি হ্যাঁ, আপাতত এটি কেবল একটি বিকাশের পরিবেশের মধ্যে চালানো যেতে পারে । পুরানো এসও পোস্টগুলিতে নতুন বৈশিষ্ট্যগুলি প্রবর্তনের ক্ষেত্রে আমি একটি প্রধান স্টার্ট পেতে চাই। ;-)
cs95

9

আমি এম কিউইচ-তে কোনও মন্তব্য যুক্ত করতে পারছি না যেহেতু আমার কাছে পর্যাপ্ত খ্যাতিমান পয়েন্ট নেই (কেবলমাত্র 41 আছে তবে মন্তব্য করার জন্য 50 এরও বেশি প্রয়োজন)।

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

>>> df = pd.DataFrame({'a': [1, 2, 3, 5], 'b': [4, np.NaN, 6, 4]})
>>> df
   a    b
0  1  4.0
1  2  NaN
2  3  6.0
3  5  4.0
>>> df.groupby(['b']).sum()
     a
b
4.0  6
6.0  3
>>> df.astype(str).groupby(['b']).sum()
      a
b
4.0  15
6.0   3
nan   2

যা দেখায় যে b = 4.0 গ্রুপের জন্য, সম্পর্কিত মানটি 6 এর পরিবর্তে 15 হবে Here এখানে এটি সংখ্যা হিসাবে যুক্ত করার পরিবর্তে 1 এবং 5 টি স্ট্রিং হিসাবে সংক্ষিপ্ত করে তুলছে।


12
এর কারণ আপনি পুরো ক্যারামটি কেবল bকলামের পরিবর্তে পুরো
কোরেম

দ্রষ্টব্য যে এখন উল্লিখিত উত্তরে এটি স্থির করা হয়েছে।
শায়াদো - মনিকা পুনরায় ইনস্টল করুন

1
আমার মতে নতুন সমাধানটি আরও ভাল তবে এখনও নিরাপদ নয়। একটি ক্ষেত্রে বিবেচনা করুন যেখানে কলাম 'খ' এ থাকা একটিতে স্ট্রিংযুক্ত এনপি.এনএএন-এর সমান। তারপরে things জিনিসগুলি একসাথে ক্লাব করা হয়। df = pd.DataFrame ({'a': [1, 2, 3, 5, 6], 'বি': ['ফু', এনপি.নান, 'বার', 'ফু', 'নান']}) ; df ['b'] = df ['b']। অ্যাস্টাইপ (স্ট্র); df.groupby (['b'])। যোগফল ()
কামারজু কুসুমাঁচি

6

অ্যান্ডি হ্যাডেনের সমাধানের জন্য একটি ছোট কথা - এটি ফল দেয় না (ফলশ্রুতিতে) কারণ np.nan == np.nanফলন ঘটে Falseতাই replaceফাংশনটি আসলে কিছুই করে না।

আমার জন্য যা কাজ করেছিল তা হ'ল:

df['b'] = df['b'].apply(lambda x: x if not np.isnan(x) else -1)

(কমপক্ষে পান্ডার 0.19.2 এর সাথে এটি আচরণ। এটিকে ভিন্ন উত্তর হিসাবে যুক্ত করার জন্য দুঃখিত, মন্তব্য করার মতো যথেষ্ট খ্যাতি আমার নেই))


12
এছাড়াও আছে df['b'].fillna(-1)
কে 3 --- আরএনসি

6

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

একটি কম হ্যাকি সমাধান হ'ল পিডি.ড্রপ_ডুলিকেট () ব্যবহার করে নিজের আইডির সাথে প্রতিটি মান সংমিশ্রণের একটি অনন্য সূচক তৈরি করতে হবে এবং তারপরে সেই আইডিতে গ্রুপ করুন। এটি আরও ভার্জোজ কিন্তু কাজটি সম্পন্ন করে:

def safe_groupby(df, group_cols, agg_dict):
    # set name of group col to unique value
    group_id = 'group_id'
    while group_id in df.columns:
        group_id += 'x'
    # get final order of columns
    agg_col_order = (group_cols + list(agg_dict.keys()))
    # create unique index of grouped values
    group_idx = df[group_cols].drop_duplicates()
    group_idx[group_id] = np.arange(group_idx.shape[0])
    # merge unique index on dataframe
    df = df.merge(group_idx, on=group_cols)
    # group dataframe on group id and aggregate values
    df_agg = df.groupby(group_id, as_index=True)\
               .agg(agg_dict)
    # merge grouped value index to results of aggregation
    df_agg = group_idx.set_index(group_id).join(df_agg)
    # rename index
    df_agg.index.name = None
    # return reordered columns
    return df_agg[agg_col_order]

নোট করুন যে আপনি এখন কেবল নিম্নলিখিতটি করতে পারেন:

data_block = [np.tile([None, 'A'], 3),
              np.repeat(['B', 'C'], 3),
              [1] * (2 * 3)]

col_names = ['col_a', 'col_b', 'value']

test_df = pd.DataFrame(data_block, index=col_names).T

grouped_df = safe_groupby(test_df, ['col_a', 'col_b'],
                          OrderedDict([('value', 'sum')]))

এটি ডামি মান হিসাবে ভুল করে এমন সত্যিকারের ডেটা ওভাররাইটিংয়ের বিষয়ে চিন্তা না করেই সফল ফলাফলটি ফিরিয়ে দেবে।


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

4

আমি ইতিমধ্যে এটির উত্তর দিয়েছি, তবে কোনও কারণে উত্তর একটি মন্তব্যে রূপান্তরিত হয়েছিল। তবুও, এটি সর্বাধিক দক্ষ সমাধান:

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

dfgrouped = df.groupby(['b']).a.agg(['sum','size','count'])

dfgrouped['sum'][dfgrouped['size']!=dfgrouped['count']] = None

যখন এগুলি পৃথক হয়, আপনি সেই গোষ্ঠীর জন্য একত্রিতকরণের ফাংশনের ফলাফলের জন্য কোনওটি মানকে আবার সেট করতে পারেন।


1
এটি আমার পক্ষে অত্যন্ত সহায়ক ছিল তবে এটি মূল প্রশ্নের চেয়ে কিছুটা আলাদা প্রশ্নের উত্তর দেয়। আইআইইউসি, আপনার দ্রবণটি সংক্ষেপে NaN গুলি প্রচার করে, তবে "বি" কলামের ন্যান আইটেমগুলি সারি হিসাবে বাদ পড়ে।
অ্যান্ড্রু

0

অ্যানাকোন্ডায় পান্ডাস 1.1 ইনস্টল করা হয়েছে

আমি সিএস 95 এর উত্তরে মন্তব্য করতে পারছি না তবে তিনি আমাকে সমস্যাটি সমাধান করতে সহায়তা করেছেন।

আমি পান্ডাস 1.1 ইনস্টল করার চেষ্টা করেছি তবে এটি তার কোড ব্যবহার করে ব্যর্থ হয়েছে, তাই আমি গুগল করে ইনস্টল করতে সক্ষম হয়েছি।

আমি প্রথমে প্রশাসক হিসাবে অ্যানাকোন্ডা প্রম্পট পরিচালনা করি এবং নিম্নলিখিত কোডটি আটকান:

pip install pandas==1.1.0rc0

এর পরে ব্যবহার অন্তর্ভুক্ত করুন dropna = False

লিঙ্ক: https://libraries.io/pypi/pandas


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