ল্যান্ড (স্ট্রিং) জড়িত শর্তাধীন অভিব্যক্তির উপর ভিত্তি করে কীন্ডেরার ডেটাফ্রেম থেকে সারিগুলি সরিয়ে ফেলুন


303

আমার কাছে একটি পান্ডাস ডেটা ফ্রেম রয়েছে এবং আমি এটি থেকে সারিগুলি মুছতে চাই যেখানে নির্দিষ্ট কলামে স্ট্রিংয়ের দৈর্ঘ্য 2 এর চেয়ে বেশি।

আমি এটি করতে সক্ষম হবেন ( এই উত্তর অনুযায়ী ):

df[(len(df['column name']) < 2)]

তবে আমি কেবল ত্রুটি পেয়েছি:

KeyError: u'no item named False'

আমি কি ভুল করছি?

(দ্রষ্টব্য: আমি জানি যে আমি df.dropna()যে কোনও NaNসারিগুলি সরিয়ে ফেলার জন্য ব্যবহার করতে পারি , তবে শর্তযুক্ত অভিব্যক্তির ভিত্তিতে সারিগুলি কীভাবে সরিয়ে ফেলতে হয় তা আমি দেখতে পাইনি))

উত্তর:


168

যখন আপনি len(df['column name'])কেবল একটি সংখ্যা পেয়ে যাচ্ছেন, যেমন ডাটাফ্রেমে সারিগুলির সংখ্যা (অর্থাত্ কলামটির দৈর্ঘ্য)। আপনি যদি lenকলামে প্রতিটি উপাদান প্রয়োগ করতে চান , ব্যবহার করুন df['column name'].map(len)। সুতরাং চেষ্টা কর

df[df['column name'].map(len) < 2]

3
আমি একটি তালিকা বোধগম্যতা ব্যবহার করে একটি উপায় নিয়ে এসেছি: df[[(len(x) < 2) for x in df['column name']]]তবে আপনারটি খুব সুন্দর। আপনার সাহায্যের জন্য ধন্যবাদ!
sjs

13
যদি কারও আরও জটিল তুলনা প্রয়োজন, একটি ল্যাম্বডা সর্বদা ব্যবহার করা যেতে পারে। df[df['column name'].map(lambda x: str(x)!=".")]
4lberto

1
কিছু কারণে, @ 4lberto পোস্ট করা ব্যতীত অন্য কোনও বিকল্পই আমার পক্ষে কাজ করে না। আমি আছি pandas 0.23.4এবং পাইথন
৩. go

1
.copy()আপনি শেষে এই ডেটাফ্রেমটি সম্পাদনা করতে চান এমন ক্ষেত্রে আমি একটি সংযোজন করব (উদাহরণস্বরূপ, নতুন কলামগুলি বরাদ্দকরণ "ডেটাফ্রেম থেকে একটি স্লাইসের অনুলিপিটিতে সেট করার চেষ্টা করছে" উত্থাপন করবে warning
প্লাজমাবিন্টুরং

806

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

df = df.drop(some labels)

df = df.drop(df[<some boolean condition>].index)

উদাহরণ

সমস্ত সারি সরাতে যেখানে কলাম 'স্কোর' <50:

df = df.drop(df[df.score < 50].index)

স্থান সংস্করণে (মতামত হিসাবে চিহ্নিত)

df.drop(df[df.score < 50].index, inplace=True)

একাধিক শর্ত

( বুলিয়ান সূচী দেখুন )

অপারেটার আছেন: |জন্য or, &জন্য and, এবং ~জন্য not। এগুলি অবশ্যই প্রথম বন্ধনী ব্যবহার করে গোষ্ঠীযুক্ত করা উচিত।

সমস্ত সারি সরাতে যেখানে কলাম 'স্কোর' <50 এবং> 20 is

df = df.drop(df[(df.score < 50) & (df.score > 20)].index)


32
আমি কেবল মন্তব্য করতে চাই, যে ড্রপ ফাংশনটি ইনপ্লেস প্রতিস্থাপনকে সমর্থন করে। অর্থাত ,. আপনার দ্রবণটি df.DP (df [df.score <50] .index, inplace = true) এর সমান। তবুও "সূচক" কৌশলটি জানতেন না। আমাকে অনেক সাহায্য করেছে
কুইকবিয়াম

9
কেবল এটিই উল্লেখ করতে চাই যে আপনি এই সূচী কৌশলটি ব্যবহার করার আগে আপনার নিশ্চিত হওয়া উচিত যে আপনার সূচক মানগুলি অনন্য (বা কল reset_index())। যখন আমি আমার ডেটাফ্রেম থেকে অনেকগুলি সারিতে যাওয়ার পথটি ফেলেছিলাম তখন আমি এটি হার্ড পথটি খুঁজে পেয়েছি।
জে

3
কলামের ধরণটি যেখানে থাকে সেখানে আমি সমস্ত সারি কীভাবে ফেলে দেব? আমি কেবল তালিকার কলামের ধরণ রাখতে চাই। আমি চেষ্টা করেছি test = df.drop(df[df['col1'].dtype == str].index)কিন্তু আমি KeyError: False চেষ্টা করেও ত্রুটি পেয়েছি df.drop(df[df.col1.dtype == str].index)এবং df.drop(df[type(df.cleaned_norm_email) == str].index)কিছুই কাজ করছে বলে মনে হচ্ছে না? কেউ পরামর্শ দিতে পারেন। ধন্যবাদ! @ ব্যবহারকারী
পিআইআরএস 16

1
এটি একটি পুরানো প্রশ্ন তবে ... @ জলজ-চ্যালেঞ্জযুক্ত মাছগুলি এর চেয়ে অনেক দ্রুত। df[(df.score < 50) & (df.score > 20)]আপনার উত্তরের অংশ হিসাবে আপনি গণনা করুন তা নোট করুন । আপনি যদি এটির বিপরীত হন তবে df = df[(df.score >= 50) | (df.score <= 20)]আপনি খুব দ্রুত আপনার উত্তর পেয়ে যাবেন।
রুবি নবি

1
@ রুবিনিবি - তাদের অবস্থা একই নয়।
এনগুই আল

106

আপনি DataFrameনিজের ফিল্টার করা সংস্করণে এটি নির্ধারণ করতে পারেন :

df = df[df.score > 50]

এটি এর চেয়ে দ্রুত drop:

%%timeit
test = pd.DataFrame({'x': np.random.randn(int(1e6))})
test = test[test.x < 0]
# 54.5 ms ± 2.02 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
test = pd.DataFrame({'x': np.random.randn(int(1e6))})
test.drop(test[test.x > 0].index, inplace=True)
# 201 ms ± 17.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
test = pd.DataFrame({'x': np.random.randn(int(1e6))})
test = test.drop(test[test.x > 0].index)
# 194 ms ± 7.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

আমি কীভাবে একাধিক কলাম ব্যবহার করে বা শর্তটি পরীক্ষা করতে পারি?
পীযূষ এস ওয়ানারে


9

একটি dropবিনামূল্যে বিকল্প সরবরাহ করার জন্য আমি @ ব্যবহারকারীর জেনেরিক সমাধানটিতে প্রসারিত করব । এটি প্রশ্নের শিরোনামের ভিত্তিতে এখানে পরিচালিত লোকদের জন্য (ওপি'র সমস্যা নয়)

বলুন আপনি নেতিবাচক মান সহ সমস্ত সারি মুছে ফেলতে চান। একটি লাইনারের সমাধান: -

df = df[(df > 0).all(axis=1)]

ধাপে ধাপে ব্যাখ্যা: -

আসুন একটি 5x5 এলোমেলো স্বাভাবিক বিতরণ ডেটা ফ্রেম তৈরি করি

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,5), columns=list('ABCDE'))
      A         B         C         D         E
0  1.764052  0.400157  0.978738  2.240893  1.867558
1 -0.977278  0.950088 -0.151357 -0.103219  0.410599
2  0.144044  1.454274  0.761038  0.121675  0.443863
3  0.333674  1.494079 -0.205158  0.313068 -0.854096
4 -2.552990  0.653619  0.864436 -0.742165  2.269755

শর্তটি sণাত্মক মোছা হোক। একটি বুলিয়ান ডিএফ শর্তটি সন্তুষ্ট করে: -

df > 0
      A     B      C      D      E
0   True  True   True   True   True
1  False  True  False  False   True
2   True  True   True   True   True
3   True  True  False   True  False
4  False  True   True  False   True

শর্তটি সন্তুষ্ট করার জন্য সমস্ত সারিগুলির জন্য একটি বুলিয়ান সিরিজ নোট করুন যদি সারিটির কোনও উপাদান শর্তটি ব্যর্থ হয় তবে সারিটি মিথ্যা চিহ্নিত করা হয়েছে

(df > 0).all(axis=1)
0     True
1    False
2     True
3    False
4    False
dtype: bool

শর্তের ভিত্তিতে অবশেষে ডেটা ফ্রেম থেকে সারিগুলি ফিল্টার আউট করুন

df[(df > 0).all(axis=1)]
      A         B         C         D         E
0  1.764052  0.400157  0.978738  2.240893  1.867558
2  0.144044  1.454274  0.761038  0.121675  0.443863

উপরের কাজগুলি বনাম ফিল্টার ইন মুছে ফেলার জন্য আপনি এটিকে আবার ডিএফ-এ নিয়োগ করতে পারেন
df = df[(df > 0).all(axis=1)]

এটি সহজেই NaN গুলি (অ-সংখ্যাযুক্ত এন্ট্রি) সহ সারিগুলিকে ফিল্টার করার জন্য বাড়ানো যেতে পারে: -
df = df[(~df.isnull()).all(axis=1)]

এটি যেমন সরল করা যেতে পারে যেমন: কলাম E negativeণাত্মক রয়েছে এমন সমস্ত সারি মুছুন

df = df[(df.E>0)]

@ ব্যবহারকারীর dropসমাধান কাঁচা কলাম ভিত্তিক পরিস্রাবণের চেয়ে ধীর: কেন কিছু প্রোফাইলিং পরিসংখ্যানের সাথে আমি শেষ করতে চাই : -

%timeit df_new = df[(df.E>0)]
345 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit dft.drop(dft[dft.E < 0].index, inplace=True)
890 µs ± 94.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

একটি কলাম মূলত একটি হল Seriesঅর্থাত একটি NumPyঅ্যারের এটা কোনো খরচ ছাড়াই সূচিবদ্ধ করা করতে পারেন। অন্তর্নিহিত মেমরি সংগঠনটি কার্যকর করার গতিতে এখানে কীভাবে আগ্রহী তা আগ্রহীদের জন্য এখানে পান্ডাদের গতি বাড়ানোর জন্য একটি দুর্দান্ত লিঙ্ক :


6

পান্ডাসে আপনি str.lenআপনার সীমানাটি দিয়ে এবং বুলিয়ান ফলাফলটি ফিল্টার করতে ব্যবহার করতে পারেন।

df[df['column name'].str.len().lt(2)]

3

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

text_data = df['name'].tolist()

এখন তালিকার প্রতিটি উপাদানটিতে কিছু ফাংশন প্রয়োগ করুন এবং এটি পান্ডা সিরিজে রাখুন:

text_length = pd.Series([func(t) for t in text_data])

আমার ক্ষেত্রে আমি কেবল টোকেনের সংখ্যা পাওয়ার চেষ্টা করছিলাম:

text_length = pd.Series([len(t.split()) for t in text_data])

ডেটা ফ্রেমে উপরের সিরিজের সাথে এখন একটি অতিরিক্ত কলাম যুক্ত করুন:

df = df.assign(text_length = text_length .values)

এখন আমরা নতুন কলামে শর্ত প্রয়োগ করতে পারি যেমন:

df = df[df.text_length  >  10]
def pass_filter(df, label, length, pass_type):

    text_data = df[label].tolist()

    text_length = pd.Series([len(t.split()) for t in text_data])

    df = df.assign(text_length = text_length .values)

    if pass_type == 'high':
        df = df[df.text_length  >  length]

    if pass_type == 'low':
        df = df[df.text_length  <  length]

    df = df.drop(columns=['text_length'])

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