পান্ডাস ডেটা ফ্রেম থেকে সারিগুলি নির্বাচন করার বিভিন্ন উপায় রয়েছে:
- বুলিয়ান ইনডেক্সিং (
df[df['col'] == value
])
- পজিশনাল ইনডেক্সিং (
df.iloc[...]
)
- লেবেল সূচক (
df.xs(...)
)
df.query(...)
এপিআই
নীচে আমি নির্দিষ্ট কৌশলগুলি কখন ব্যবহার করব সে বিষয়ে পরামর্শ সহ প্রত্যেকটির উদাহরণ দেখাব। ধরুন আমাদের মানদণ্ডটি কলাম 'A'
=='foo'
(পারফরম্যান্সের উপর নোট: প্রতিটি বেস টাইপের জন্য, আমরা পান্ডাস এপিআই ব্যবহার করে জিনিসগুলিকে সহজ রাখতে পারি বা আমরা সাধারণত এপিআই এর বাইরে numpy
, এবং জিনিসগুলিকে গতি বাড়িয়ে তুলতে পারি))
সেটআপ
আমাদের প্রথম জিনিসটির প্রয়োজন হবে একটি শর্ত চিহ্নিত করা যা সারিগুলি নির্বাচন করার জন্য আমাদের মানদণ্ড হিসাবে কাজ করবে। আমরা ওপি'র কেসটি দিয়ে শুরু করব column_name == some_value
, এবং কিছু সাধারণ ব্যবহারের কেস অন্তর্ভুক্ত করব।
@ ইউনতবু থেকে ingণ নেওয়া:
import pandas as pd, numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
'B': 'one one two three two two one three'.split(),
'C': np.arange(8), 'D': np.arange(8) * 2})
1. বুলিয়ান সূচীকরণ
... বুলিয়ান ইনডেক্সিংয়ের জন্য প্রতিটি সারির 'A'
কলামের সমান হওয়াতে তার সঠিক মান খুঁজে পাওয়া দরকার এবং 'foo'
তারপরে কোন সারিগুলি রাখা উচিত তা সনাক্ত করতে সেই সত্যের মানগুলি ব্যবহার করে। সাধারণত, আমরা এই সিরিজটির নাম দেব, সত্যের মূল্যবোধগুলির একটি অ্যারে mask
,। আমরা এখানেও তাই করব।
mask = df['A'] == 'foo'
এরপরে আমরা এই মুখোশটি ডেটা ফ্রেমকে টুকরো টুকরো করতে বা সূচি করতে ব্যবহার করতে পারি can
df[mask]
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
এই কাজটি সম্পাদন করার এটি সহজতম উপায়গুলির মধ্যে একটি এবং যদি পারফরম্যান্স বা স্বজ্ঞাততা কোনও সমস্যা না হয় তবে এটি আপনার চয়ন করা পদ্ধতি হওয়া উচিত। তবে, কর্মক্ষমতা যদি উদ্বেগের বিষয় হয় তবে আপনি এটি তৈরির বিকল্প উপায় বিবেচনা করতে পারেন mask
।
2. পজিশনাল ইনডেক্সিং
পজিশনাল ইনডেক্সিং ( df.iloc[...]
) এর ব্যবহারের কেস রয়েছে তবে এটি তাদের মধ্যে একটি নয়। কোথায় টুকরো টুকরো টুকরো টুকরো তা চিহ্নিত করার জন্য প্রথমে আমাদের উপরে একই বুলিয়ান বিশ্লেষণ করা দরকার। এটি একই কাজ সম্পাদন করতে আমাদের আরও একটি পদক্ষেপ সম্পাদন করে leaves
mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
3. লেবেল সূচীকরণ
লেবেল সূচিকরণ খুব সহজ হতে পারে, তবে এই ক্ষেত্রে আমরা আবার কোনও লাভের জন্য আরও কাজ করছি
df.set_index('A', append=True, drop=False).xs('foo', level=1)
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
4. df.query()
এপিআই
pd.DataFrame.query
এই কাজটি সম্পাদন করার জন্য খুব মার্জিত / স্বজ্ঞাত উপায়, তবে প্রায়শই ধীর হয়। তবে , যদি আপনি নীচের সময়গুলিতে মনোযোগ দেন তবে বড় ডেটার জন্য, ক্যোয়ারীটি খুব দক্ষ। আমার সর্বোত্তম পরামর্শ হিসাবে স্ট্যান্ডার্ড পদ্ধতির এবং অনুরূপ বিশালতার চেয়ে বেশি।
df.query('A == "foo"')
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
আমার পছন্দটি ব্যবহার করা Boolean
mask
আমরা কীভাবে তৈরি করব তা পরিবর্তনের মাধ্যমে প্রকৃত উন্নতি করা যেতে পারে Boolean
mask
।
mask
বিকল্প 1
অন্তর্নিহিত numpy
অ্যারে ব্যবহার করুন এবং অন্যটি তৈরি করার ওভারহেডটি রেখে যানpd.Series
mask = df['A'].values == 'foo'
আমি শেষে আরও সম্পূর্ণ সময়ের পরীক্ষাগুলি দেখাব, তবে কেবলমাত্র নমুনা ডেটা ফ্রেম ব্যবহার করে আমরা যে পারফরম্যান্স লাভ করেছি তা একবার দেখুন। প্রথমত, আমরা তৈরির পার্থক্যটি দেখিmask
%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'
5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
অ্যারের mask
সাথে মূল্যায়ন numpy
করা ~ 30 গুণ দ্রুত। এটি আংশিকভাবে numpy
মূল্যায়নের কারণে প্রায়শই দ্রুত হয়। এটি একটি আংশিক কারণ একটি সূচক এবং এর সাথে সম্পর্কিত pd.Series
কোনও বস্তু তৈরি করার জন্য প্রয়োজনীয় ওভারহেডের অভাবের কারণেও রয়েছে ।
এরপরে, আমরা একে অন্যের mask
বিপরীতে কাটানোর সময়টি লক্ষ্য করব ।
mask = df['A'].values == 'foo'
%timeit df[mask]
mask = df['A'] == 'foo'
%timeit df[mask]
219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
পারফরম্যান্স লাভগুলি যেমন উচ্চারণ হয় না। এটি আরও শক্তিশালী পরীক্ষার উপর নির্ভর করে কিনা তা আমরা দেখতে পাব।
mask
বিকল্প 2
আমরা পাশাপাশি ডেটা ফ্রেমটি পুনর্গঠন করতে পারতাম। ডেটাফ্রেমের পুনর্গঠন করার সময় একটি বড় সতর্কতা রয়েছে — আপনাকে অবশ্যই এর যত্ন নেওয়া উচিতdtypes
সময় !
পরিবর্তে df[mask]
আমরা এই কাজ করব
pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)
যদি ডেটা ফ্রেমটি মিশ্র প্রকারের হয়, যা আমাদের উদাহরণ, তবে আমরা যখন df.values
ফলস্বরূপ অ্যারে পাই dtype
object
এবং ফলস্বরূপ, নতুন ডেটা ফ্রেমের সমস্ত কলাম হবে dtype
object
। এইভাবে astype(df.dtypes)
কোনও সম্ভাব্য পারফরম্যান্স লাভের প্রয়োজন এবং হত্যার জন্য।
%timeit df[m]
%timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)
216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
যাইহোক, যদি ডেটা ফ্রেমটি মিশ্র প্রকারের না হয় তবে এটি করার জন্য এটি খুব দরকারী।
প্রদত্ত
np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))
d1
A B C D E
0 0 2 7 3 8
1 7 0 6 8 6
2 0 2 0 4 9
3 7 3 2 4 3
4 3 6 7 7 4
5 5 3 7 5 9
6 8 7 6 4 7
7 6 2 6 6 5
8 2 8 7 5 8
9 4 7 6 1 5
%%timeit
mask = d1['A'].values == 7
d1[mask]
179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
বনাম
%%timeit
mask = d1['A'].values == 7
pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns)
87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
আমরা সময় অর্ধেক কাটা।
mask
বিকল্প 3
@ ইউন্টবুও আমাদের দেখায় যে কীভাবে pd.Series.isin
প্রতিটি df['A']
মানগুলির একটি সংখ্যায় থাকা প্রতিটি উপাদানগুলির জন্য অ্যাকাউন্টে ব্যবহার করতে হয় । এটি একই জিনিসকে মূল্যায়ন করে যদি আমাদের মানগুলির সেটটি একটি মানের একটি সেট হয়, যথা 'foo'
। তবে এটি প্রয়োজনে বড় আকারের মানগুলি অন্তর্ভুক্ত করতে সাধারণীকরণ করে। দেখা যাচ্ছে, এটি আরও সাধারণ সমাধান হওয়া সত্ত্বেও এটি এখনও বেশ দ্রুত। একমাত্র আসল ক্ষতি হ'ল এই ধারণার সাথে পরিচিত নয় তাদের ক্ষেত্রে স্বজ্ঞাততা।
mask = df['A'].isin(['foo'])
df[mask]
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
যাইহোক, numpy
পূর্বের মতো, কার্যত কিছুই বলিদানের সময় আমরা পারফরম্যান্স উন্নত করতে ব্যবহার করতে পারি । আমরা ব্যবহার করবnp.in1d
mask = np.in1d(df['A'].values, ['foo'])
df[mask]
A B C D
0 foo one 0 0
2 foo two 2 4
4 foo two 4 8
6 foo one 6 12
7 foo three 7 14
সময় নির্ধারণের জন্য
আমি অন্যান্য পোস্টে উল্লিখিত অন্যান্য ধারণাগুলিও অন্তর্ভুক্ত করব।
নীচে কোড
এই টেবিলের প্রতিটি কলাম একটি পৃথক দৈর্ঘ্যের ডেটা ফ্রেম উপস্থাপন করে যার উপরে আমরা প্রতিটি ফাংশন পরীক্ষা করি। প্রতিটি কলামটি তুলনামূলকভাবে সময় নিয়েছে, এর সাথে বেজ সূচককে দেওয়া দ্রুততম ফাংশন 1.0
।
res.div(res.min())
10 30 100 300 1000 3000 10000 30000
mask_standard 2.156872 1.850663 2.034149 2.166312 2.164541 3.090372 2.981326 3.131151
mask_standard_loc 1.879035 1.782366 1.988823 2.338112 2.361391 3.036131 2.998112 2.990103
mask_with_values 1.010166 1.000000 1.005113 1.026363 1.028698 1.293741 1.007824 1.016919
mask_with_values_loc 1.196843 1.300228 1.000000 1.000000 1.038989 1.219233 1.037020 1.000000
query 4.997304 4.765554 5.934096 4.500559 2.997924 2.397013 1.680447 1.398190
xs_label 4.124597 4.272363 5.596152 4.295331 4.676591 5.710680 6.032809 8.950255
mask_with_isin 1.674055 1.679935 1.847972 1.724183 1.345111 1.405231 1.253554 1.264760
mask_with_in1d 1.000000 1.083807 1.220493 1.101929 1.000000 1.000000 1.000000 1.144175
আপনি লক্ষ্য করবেন যে দ্রুততম সময়গুলি mask_with_values
এবং এর মধ্যে ভাগ করা বলে মনে হচ্ছেmask_with_in1d
res.T.plot(loglog=True)
ক্রিয়াকলাপ
def mask_standard(df):
mask = df['A'] == 'foo'
return df[mask]
def mask_standard_loc(df):
mask = df['A'] == 'foo'
return df.loc[mask]
def mask_with_values(df):
mask = df['A'].values == 'foo'
return df[mask]
def mask_with_values_loc(df):
mask = df['A'].values == 'foo'
return df.loc[mask]
def query(df):
return df.query('A == "foo"')
def xs_label(df):
return df.set_index('A', append=True, drop=False).xs('foo', level=-1)
def mask_with_isin(df):
mask = df['A'].isin(['foo'])
return df[mask]
def mask_with_in1d(df):
mask = np.in1d(df['A'].values, ['foo'])
return df[mask]
পরীক্ষামূলক
res = pd.DataFrame(
index=[
'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
],
columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
dtype=float
)
for j in res.columns:
d = pd.concat([df] * j, ignore_index=True)
for i in res.index:a
stmt = '{}(d)'.format(i)
setp = 'from __main__ import d, {}'.format(i)
res.at[i, j] = timeit(stmt, setp, number=50)
বিশেষ সময় সম্পূর্ণ
বিভাগের dtype
ফ্রেমের জন্য যখন আমাদের একক অ-অবজেক্ট থাকে তখন বিশেষ ক্ষেত্রে তাকানো।
নীচে কোড
spec.div(spec.min())
10 30 100 300 1000 3000 10000 30000
mask_with_values 1.009030 1.000000 1.194276 1.000000 1.236892 1.095343 1.000000 1.000000
mask_with_in1d 1.104638 1.094524 1.156930 1.072094 1.000000 1.000000 1.040043 1.027100
reconstruct 1.000000 1.142838 1.000000 1.355440 1.650270 2.222181 2.294913 3.406735
দেখা যাচ্ছে, কয়েকশো সারি পেরিয়ে পুনর্নির্মাণের পক্ষে এটি উপযুক্ত নয়।
spec.T.plot(loglog=True)
ক্রিয়াকলাপ
np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))
def mask_with_values(df):
mask = df['A'].values == 'foo'
return df[mask]
def mask_with_in1d(df):
mask = np.in1d(df['A'].values, ['foo'])
return df[mask]
def reconstruct(df):
v = df.values
mask = np.in1d(df['A'].values, ['foo'])
return pd.DataFrame(v[mask], df.index[mask], df.columns)
spec = pd.DataFrame(
index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
dtype=float
)
পরীক্ষামূলক
for j in spec.columns:
d = pd.concat([df] * j, ignore_index=True)
for i in spec.index:
stmt = '{}(d)'.format(i)
setp = 'from __main__ import d, {}'.format(i)
spec.at[i, j] = timeit(stmt, setp, number=50)