দুটি তারিখের মধ্যে ডেটা ফ্রেম সারি নির্বাচন করুন


196

আমি সিএসভি থেকে একটি ডেটা ফ্রেম তৈরি করছি:

stock = pd.read_csv('data_in/' + filename + '.csv', skipinitialspace=True)

ডেটাফ্রেমের একটি তারিখ কলাম রয়েছে। একটি নতুন ডেটাফ্রেম তৈরি করার কোনও উপায় আছে (বা কেবলমাত্র বিদ্যমানটিকে ওভাররাইট করে) যেখানে কেবলমাত্র নির্দিষ্ট তারিখের মধ্যে বা দুটি নির্দিষ্ট তারিখের মানের মধ্যে পড়ে এমন তারিখের মান সহ সারি থাকে?

উত্তর:


399

দুই সম্ভাব্য সমাধান আছে:

  • বুলিয়ান মাস্ক ব্যবহার করুন, তারপরে ব্যবহার করুন df.loc[mask]
  • ডেটটাইম ইন্ডেক্স হিসাবে তারিখের কলাম সেট করুন, তারপরে ব্যবহার করুন df[start_date : end_date]

বুলিয়ান মাস্ক ব্যবহার :

নিশ্চিত করুন df['date']dtype সহ একটি সিরিজ datetime64[ns]:

df['date'] = pd.to_datetime(df['date'])  

একটি বুলিয়ান মাস্ক তৈরি করুন। start_dateএবং end_dateহতে পারে datetime.datetimeS, np.datetime64S, pd.Timestampগুলি, অথবা এমনকি DATETIME স্ট্রিং:

#greater than the start date and smaller than the end date
mask = (df['date'] > start_date) & (df['date'] <= end_date)

সাব-ডেটা ফ্রেম নির্বাচন করুন:

df.loc[mask]

বা পুনরায় নিয়োগ df

df = df.loc[mask]

উদাহরণ স্বরূপ,

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.random((200,3)))
df['date'] = pd.date_range('2000-1-1', periods=200, freq='D')
mask = (df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')
print(df.loc[mask])

উৎপাদনের

            0         1         2       date
153  0.208875  0.727656  0.037787 2000-06-02
154  0.750800  0.776498  0.237716 2000-06-03
155  0.812008  0.127338  0.397240 2000-06-04
156  0.639937  0.207359  0.533527 2000-06-05
157  0.416998  0.845658  0.872826 2000-06-06
158  0.440069  0.338690  0.847545 2000-06-07
159  0.202354  0.624833  0.740254 2000-06-08
160  0.465746  0.080888  0.155452 2000-06-09
161  0.858232  0.190321  0.432574 2000-06-10

ডেটটাইম ইন্ডেক্স ব্যবহার করে :

আপনি যদি তারিখ অনুসারে অনেকগুলি নির্বাচন করতে যাচ্ছেন তবে dateকলামটি প্রথমে সূচক হিসাবে সেট করা দ্রুত হতে পারে । তারপরে আপনি ব্যবহার করে তারিখ অনুসারে সারি নির্বাচন করতে পারেন df.loc[start_date:end_date]

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.random((200,3)))
df['date'] = pd.date_range('2000-1-1', periods=200, freq='D')
df = df.set_index(['date'])
print(df.loc['2000-6-1':'2000-6-10'])

উৎপাদনের

                   0         1         2
date                                    
2000-06-01  0.040457  0.326594  0.492136    # <- includes start_date
2000-06-02  0.279323  0.877446  0.464523
2000-06-03  0.328068  0.837669  0.608559
2000-06-04  0.107959  0.678297  0.517435
2000-06-05  0.131555  0.418380  0.025725
2000-06-06  0.999961  0.619517  0.206108
2000-06-07  0.129270  0.024533  0.154769
2000-06-08  0.441010  0.741781  0.470402
2000-06-09  0.682101  0.375660  0.009916
2000-06-10  0.754488  0.352293  0.339337

পাইথন তালিকার সূচীকরণের ক্ষেত্রে, যেমন seq[start:end]অন্তর্ভুক্ত রয়েছে startতবে endএর বিপরীতে নয়, পান্ডাস সূচকে থাকলে ফলাফলের উভয় প্রান্ত-পয়েন্ট df.loc[start_date : end_date]অন্তর্ভুক্ত করে । আমরাও start_dateনা end_dateতবে সূচক হতে হয়েছে।


এছাড়াও খেয়াল করুন যে pd.read_csvএর একটি parse_datesপ্যারামিটার রয়েছে যা আপনি dateকলামটিকে datetime64গুলি হিসাবে পার্স করতে ব্যবহার করতে পারেন । সুতরাং, আপনি যদি ব্যবহার করেন parse_dates, আপনার ব্যবহারের প্রয়োজন হবে না df['date'] = pd.to_datetime(df['date'])


সূচী হিসাবে তারিখের কলামটি সেট করা ভাল কাজ করে তবে ডকুমেন্টেশন থেকে এটি স্পষ্ট নয় যে আমি দেখেছি যে কেউ এটি করতে পারে। ধন্যবাদ।
ফাহিম মিঠা 16'19

@ ফাহিমমিঠা: আমি উপরে একটি লিঙ্ক যুক্ত করেছি যেখানে "আংশিক স্ট্রিং ইন্ডেক্সিং" নথিভুক্ত করা হয়েছে।
unutbu

যে অংশটি সম্ভবত কম স্পষ্ট তা হ'ল একটি সূচক স্পষ্টভাবে তৈরি করতে হবে। এবং সুস্পষ্টভাবে সূচক তৈরি না করেই, একটি সীমাবদ্ধ পরিসীমা একটি ত্রুটি নয়, খালি সেট দেয়।
ফাহিম মিঠা 16'19

8
df = df.set_index(['date'])পদক্ষেপের পরে , আমি df.sort_index(inplace=True, ascending=True)সূচকটিও বাছাই করতে পেরেছি (এর মাধ্যমে ), অন্যথায় আপনি পূর্ণ বা এমনকি খালি ডেটা ফ্রেমের ফলাফল থেকে কম পেতে পারেন df.loc['2000-6-1':'2000-6-10']। এবং আপনি যদি এটি ব্যবহার ascending=Falseকরেন তবে এটি df.loc['2000-6-10':'2000-6-1']
কোনওভাবেই

আপনি যদি এখনও ডেটাফ্রেমের সূচকে এর মান দিতে গিয়ে 'তারিখ' কলামটি রাখতে চান তবে আপনি এই df.index = df ['তারিখ'] করতে পারেন
রিচার্ড লিয়াং

64

আমি মনে করি সবচেয়ে ভাল বিকল্পটি হ'ল লোক ফাংশন ব্যবহার না করে সরাসরি চেক ব্যবহার করা হবে:

df = df[(df['date'] > '2000-6-1') & (df['date'] <= '2000-6-10')]

এটা আমার জন্য কাজ করে.

একটি স্লাইস সহ লোক ফাংশন সহ প্রধান সমস্যাটি হ'ল সীমাগুলি প্রকৃত মানগুলিতে উপস্থিত হওয়া উচিত, যদি তা না হয় তবে কীআরারের ফলাফল হবে।


আমি মনে করি এর মাধ্যমে স্লাইসগুলি locদুর্দান্ত। এবং এটি আমার কাছে মনে হয় যে আনটবু যেমন বলেছে, সূচি-তালিকার বা শেষের তারিখের কোনওটিই সূচকে থাকতে হবে না
নীলামকবি

কীভাবে তারিখটি ফিল্টার করবেন (বর্তমান তারিখের 14 দিন আগে) .. আজকের তারিখটি যদি 2019-01-15 হয় ... আমার কাছে তথ্য প্রয়োজন (2019-01-01
প্রবীণ তুষার

সহজ এবং মার্জিত। ধন্যবাদ ক্রিস্টিন, আমি এটাই করার চেষ্টা করছিলাম। আমার জন্য কাজ কর.
ব্রহজো

35

আপনি এটি ব্যবহার করতে পারেন between:

df[df.some_date.between(start_date, end_date)]

2
এছাড়াও দেখুন between_time: pandas.pydata.org/pandas-docs/version/0.20.3/generated/…
আন্তন

@AntonTarasenko স্ট্রেঞ্জলি, সাথে কাজ করে না datetimes শুধুমাত্র, বরং বার । এই পার্থক্যটি উপলব্ধি করতে আমাকে কিছুক্ষণ সময় নিয়েছে। এই থ্রেডের সাথে পরামর্শ করেই শেষ করেছি।
রটিন

19

আপনি যেমন কলামে isinপদ্ধতিটি ব্যবহার করতে পারেনdatedf[df["date"].isin(pd.date_range(start_date, end_date))]

দ্রষ্টব্য: এটি কেবল তারিখগুলি নিয়ে কাজ করে (যেমন প্রশ্ন জিজ্ঞাসা করে) এবং টাইমস্ট্যাম্পগুলি নয়।

উদাহরণ:

import numpy as np   
import pandas as pd

# Make a DataFrame with dates and random numbers
df = pd.DataFrame(np.random.random((30, 3)))
df['date'] = pd.date_range('2017-1-1', periods=30, freq='D')

# Select the rows between two dates
in_range_df = df[df["date"].isin(pd.date_range("2017-01-15", "2017-01-20"))]

print(in_range_df)  # print result

যা দেয়

           0         1         2       date
14  0.960974  0.144271  0.839593 2017-01-15
15  0.814376  0.723757  0.047840 2017-01-16
16  0.911854  0.123130  0.120995 2017-01-17
17  0.505804  0.416935  0.928514 2017-01-18
18  0.204869  0.708258  0.170792 2017-01-19
19  0.014389  0.214510  0.045201 2017-01-20

9

সমাধানটি সহজ এবং অজগরটিকে রেখে, আমি আপনাকে এটি চেষ্টা করার পরামর্শ দিচ্ছি।

যদি আপনি এটি ঘন ঘন করতে চলেছেন তবে সর্বোত্তম সমাধান হ'ল প্রথমে তারিখের কলামটি সূচক হিসাবে সেট করে যা ডেটটাইম ইন্ডেক্সে কলামটি রূপান্তর করবে এবং যে কোনও তারিখের বিস্তৃত অংশের জন্য নিম্নলিখিত শর্তটি ব্যবহার করবে।

import pandas as pd

data_frame = data_frame.set_index('date')

df = data_frame[(data_frame.index > '2017-08-10') & (data_frame.index <= '2017-08-15')]

4

আমার pandasসংস্করণটির পরীক্ষার মাধ্যমে 0.22.0আপনি এখন আরও সহজভাবে ব্যবহার করে আরও পঠনযোগ্য কোডের মাধ্যমে এই প্রশ্নের উত্তর দিতে পারবেন between

# create a single column DataFrame with dates going from Jan 1st 2018 to Jan 1st 2019
df = pd.DataFrame({'dates':pd.date_range('2018-01-01','2019-01-01')})

ধরা যাক আপনি 27 শে নভেম্বর 2018 থেকে 15 ই জানুয়ারী 2019 এর মধ্যে তারিখগুলি দখল করতে চান:

# use the between statement to get a boolean mask
df['dates'].between('2018-11-27','2019-01-15', inclusive=False)

0    False
1    False
2    False
3    False
4    False

# you can pass this boolean mask straight to loc
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=False)]

    dates
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01
335 2018-12-02

অন্তর্ভুক্তি যুক্তি লক্ষ্য করুন। আপনি যখন আপনার পরিসীমা সম্পর্কে সুস্পষ্ট হতে চান তখন খুব সহায়ক। সত্য হিসাবে সেট করা হলে বিজ্ঞপ্তি আমরা 2018 সালের 27 নভেম্বরও ফিরে আসছি:

df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]

    dates
330 2018-11-27
331 2018-11-28
332 2018-11-29
333 2018-11-30
334 2018-12-01

এই পদ্ধতিটি পূর্বে উল্লিখিত isinপদ্ধতির চেয়েও দ্রুত :

%%timeit -n 5
df.loc[df['dates'].between('2018-11-27','2019-01-15', inclusive=True)]
868 µs ± 164 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)


%%timeit -n 5

df.loc[df['dates'].isin(pd.date_range('2018-01-01','2019-01-01'))]
1.53 ms ± 305 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)

তবে এটি বর্তমানে গৃহীত উত্তরের চেয়ে দ্রুত নয় , আনটবু দ্বারা সরবরাহ করা, কেবল যদি মুখোশটি ইতিমধ্যে তৈরি করা হয় । তবে যদি মুখোশটি গতিশীল হয় এবং বারবার পুনরায় নিয়োগ করা প্রয়োজন হয় তবে আমার পদ্ধতিটি আরও দক্ষ হতে পারে:

# already create the mask THEN time the function

start_date = dt.datetime(2018,11,27)
end_date = dt.datetime(2019,1,15)
mask = (df['dates'] > start_date) & (df['dates'] <= end_date)

%%timeit -n 5
df.loc[mask]
191 µs ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 5 loops each)

3

আমি পরিবর্তন না পছন্দ df

একটি বিকল্প পুনরুদ্ধার করতে হয় indexএর startএবং endতারিখ:

import numpy as np   
import pandas as pd

#Dummy DataFrame
df = pd.DataFrame(np.random.random((30, 3)))
df['date'] = pd.date_range('2017-1-1', periods=30, freq='D')

#Get the index of the start and end dates respectively
start = df[df['date']=='2017-01-07'].index[0]
end = df[df['date']=='2017-01-14'].index[0]

#Show the sliced df (from 2017-01-07 to 2017-01-14)
df.loc[start:end]

যার ফলাফল:

     0   1   2       date
6  0.5 0.8 0.8 2017-01-07
7  0.0 0.7 0.3 2017-01-08
8  0.8 0.9 0.0 2017-01-09
9  0.0 0.2 1.0 2017-01-10
10 0.6 0.1 0.9 2017-01-11
11 0.5 0.3 0.9 2017-01-12
12 0.5 0.4 0.3 2017-01-13
13 0.4 0.9 0.9 2017-01-14

3

আরেকটি বিকল্প, এটি কীভাবে অর্জন করা যায় তা হল pandas.DataFrame.query()পদ্ধতি ব্যবহার করে । নীচে ডাকা ডাটা ফ্রেমে আমি আপনাকে একটি উদাহরণ দেখাচ্ছি df

>>> df = pd.DataFrame(np.random.random((5, 1)), columns=['col_1'])
>>> df['date'] = pd.date_range('2020-1-1', periods=5, freq='D')
>>> print(df)
      col_1       date
0  0.015198 2020-01-01
1  0.638600 2020-01-02
2  0.348485 2020-01-03
3  0.247583 2020-01-04
4  0.581835 2020-01-05

যুক্তি হিসাবে, ফিল্টারিংয়ের জন্য এই শর্তটি ব্যবহার করুন:

>>> start_date, end_date = '2020-01-02', '2020-01-04'
>>> print(df.query('date >= @start_date and date <= @end_date'))
      col_1       date
1  0.244104 2020-01-02
2  0.374775 2020-01-03
3  0.510053 2020-01-04

আপনি যদি সীমানা অন্তর্ভুক্ত করতে না চান তবে কেবল নীচের মতো শর্তটি পরিবর্তন করুন:

>>> print(df.query('date > @start_date and date < @end_date'))
      col_1       date
2  0.374775 2020-01-03
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.