Eddie Winch Ответов: 1

Фильтрация строк в фрейме данных pandas с учетом дня и месяца


Привет там у меня есть следующий код, который я запускаю в Jupyter Notebook :-

<pre>import pandas as pd
import requests
from bs4 import BeautifulSoup
   
#res = requests.get("http://web.archive.org/web/20011108193342/http://www.raf.mod.uk/bbmf/calendar.html")     
res = requests.get("http://web.archive.org/web/20041020000138/http://www.raf.mod.uk/bbmf/displaydates.html")
soup = BeautifulSoup(res.content,'lxml')
table = soup.find_all('table', align="CENTER")[0]
df = pd.read_html(str(table))
   
df = df[0]
  
  
##################
##################
##################
  
  
pd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
 
 
#make df[0] to list
list=[]
for i in df[0]:
    list.append(i)
  
#reverse the list to make split to sublist easier
list.reverse()
  
#split list to sublist using condition len(val)> 2 
size = len(list) 
idx_list = [idx + 1 for idx, val in
            enumerate(list) if len(val) > 2] 
res = [list[i: j] for i, j in
        zip([0] + idx_list, idx_list + 
        ([size] if idx_list[-1] != size else []))] 
  
#make monthname to numbers and print
for i in res:
    for j in range(len(i)):
        if i[j].upper()=='JUNE':
            i[j]='6'
        elif i[j].upper() =='MAY':
            i[j]='5'
        elif i[j].upper() == 'APRIL':
            i[j]='4'
        elif i[j].upper() =='JANUARY':
            i[j]='1'
        elif i[j].upper() == 'FEBRUARY':
            i[j]='2'
        elif i[j].upper() =='MARCH':
            i[j]='3'
        elif i[j].upper() == 'JULY':
            i[j]='7'        
        elif i[j].upper() =='AUGUST':
            i[j]='8'
        elif i[j].upper() == 'SEPTEMBER':
            i[j]='9'
        elif i[j].upper() =='OCTOBER':
            i[j]='10'
        elif i[j].upper() == 'NOVEMBER':
            i[j]='11'
        elif i[j].upper() =='DECEMBER':
            i[j]='12'       
  
  
#append string and append to new list
finallist=[]
for i in res:
    for j in range(len(i)):
        if j < len(i) - 1:
            #print(f'2004-{i[-1]}-{i[j]}')
            finallist.append(f'2004-{i[-1]}-{i[j]}')
#print(finallist)
finallist.reverse()
  
  
  
  
#print("\n=== ORIGINAL DF ===\n")
#print(df)
  
  
  
#convert dataframe to list
listtemp1=df.values.tolist()
  
#replace found below values with 0000_removable
removelist=['LOCATION','LANCASTER','SPITFIRE','HURRICANE','DAKOTA','DATE','JUNE','JANUARY','FEBRUARY','MARCH','MAY','JULY','AUGUST','SEPTEMBER','OCTOBER','NOVEMBER','DECEMBER','APRIL']
for i in listtemp1:
    for j in range(len(i)):
        for place in removelist:
            if str(i[j]).upper()==place:
                i[j]='0000_removable'
            else:
                pass
  
                  
#remove sublists with the replaced values we redirected
dellist=['0000_removable', '0000_removable', '0000_removable', '0000_removable', '0000_removable', '0000_removable']
res = [i for i in listtemp1 if i != dellist]
  
#assign back to dataframe DF3
df3=pd.DataFrame()
df3=pd.DataFrame(res, columns=['Date','LOCATION','LANCASTER','SPITFIRE','HURRICANE','DAKOTA'])
#print("\n=== AFTER REMOVE month and column names from DF, assigned to new as DF3 ===\n")
#print(df3)
  
  
#now assign that sorted date list to dataframe DF3
idx = 0
df3.insert(loc=idx, column='DATE', value=finallist)
pd.options.display.max_rows = 500
  
#print("\n=== FINAL DF3 after joining the edited date format column list ===\n")
#print(df3)
  
  
#validation logic if needed compare processed date from new joined "edited_Date_format" column with already existing "Date" column
#df3['ED1']=  pd.to_datetime(df3['EDITED_DATE_FORMAT'],format='%Y-%m-%d').dt.day
#df3['validation of date'] = df3.apply(lambda x: str(x['ED1']) == x['Date'], axis=1)
  
  
#convert df3['EDITED_DATE_FORMAT'] column from object to datetime64 foramt
#df3['EDITED_DATE_FORMAT']= pd.to_datetime(df3['EDITED_DATE_FORMAT'],format='%Y-%m-%d')
  
  
  
##################
##################
##################
  
  
 
 
  
 
#df3 = df3.rename(columns=df.iloc[0])
#df3 = df.iloc[2:]
#df3.head(15)
pd.options.display.max_rows = 1000
pd.options.display.max_columns = 1000

df3['LANCASTER'] = df3['LANCASTER'].replace({'X': 'L'})
df3['HURRICANE'] = df3['HURRICANE'].replace({'X': 'H'})
df3['SPITFIRE'] = df3['SPITFIRE'].replace({'X': 'S'})
df3['SPITFIRE'] = df3['SPITFIRE'].replace({'X x 2': 'SS'})
df3['DAKOTA'] = df3['DAKOTA'].replace({'X': 'D'})


#display = df3[(df3['LOCATION'].str.contains('[a-zA-Z]')) & (df3['DAKOTA'].str.contains('X')) & (df3['SPITFIRE'].str.contains('X', na=True)) & (df3['LANCASTER'] != 'X')]    
#display = df3[(df3['LOCATION'].str.contains('[a-zA-Z]')) & (df3['DAKOTA'].str.contains('D')) & (df3['SPITFIRE'].str.contains('S', na=True)) & (df3['LANCASTER'] != 'L')]    
    
display = df3[(df3['LOCATION'].str.contains('[a-zA-Z]')) & (df3['DATE'].str.contains('-10$|15$')) & (df3['DAKOTA'].str.contains('D')) & (df3['SPITFIRE'].str.contains('S', na=True)) & (df3['LANCASTER'] != 'L')]    
    
#Months = May Jun Jul Aug Sep
#Months = -5- -6- -7- -8- -9-

#print(display) 

display['DATE']= pd.to_datetime(display['DATE'],format='%Y-%m-%d')
display['DATE']= pd.to_datetime(display['DATE']).dt.strftime('%m-%d-%Y')
##added two lines above to convert date format

display=display.rename_axis('MyIdx')
display=display.sort_values(by=['DATE','MyIdx'])
display['DATE']= pd.to_datetime(display['DATE']).dt.strftime('%d-%b-%Y')
#display.drop_duplicates(subset=['LOCATION', 'DATE'], keep='last', inplace=True)

#display.drop('LANCASTER', axis=1, inplace=True)
#display.drop('Date', axis=1, inplace=True)
display=display.dropna(subset=['SPITFIRE', 'HURRICANE'], how='all')
display=display[['LOCATION','DATE','DAKOTA','HURRICANE','SPITFIRE']]
display=display.fillna('--')
#display.reset_index(drop=True, inplace=True)
display.to_csv(r'C:\Users\Edward\Desktop\BBMF Schedules And Master Forum Thread Texts\BBMF-2004-Code (Dakota With Fighters).csv')


display

display.sort_values(by=['DATE'])

#print(display)


И когда я включаю эту последнюю строку кода, она правильно выводит самые ранние дни в выводе фрейма данных сначала, то есть от 10 до 15, но не в том порядке месяцев, который я хочу :-


МЕСТО ПРОВЕДЕНИЯ ДАТА ДАКОТА УРАГАН СПИТФАЙР
MyIdx
176 Даксфорд 10-Июль-2004 D H S
177 Сайренчестер 10-Июль-2004 D H S
178 Brize Norton 10-Jul-2004 D H S
74 Shrivenham 20:00 10 Июня 2004 Д Ч Ы
257 Кэмпблтаун 15-Авг-2004 D -- S
258 Сандерленд 15-Авг-2004 D -- S
261 Scampton 15-Aug-2004 D -- S
200 RIAT Fairford 15-Jul-2004 D -- SS
22 Tilford 15-May-2004 D -- S
23 Abingdon 15-May-2004 D -- S
24 Hyde Heath Village 15-May-2004 D -- S

Я хочу, чтобы сначала было 10 июня 2004 года, затем 10 июля/С, затем 15 мая, затем 15 июля, затем 15 августа. Как мне изменить эту строку кода, чтобы я мог фильтровать, чтобы получить этот порядок, не изменяя индексную позицию строк с помощью кода, который я знаю, как это сделать ?

Я имею в виду добавить что-то в первую строку кода, например строку displays.sort_values, чтобы более ранний месяц с днем показывался "предпочтительным" перед более поздним месяцем с тем же днем ? т. е. 10-Jun-2004 отображается перед 10-Jul-2004 , 15-May-2004 отображается перед 15-Jul-2004 строками и т. д. Но все же даты с 10-го дня показывают до 15-го дня строки.

(df3['DATE'].str.contains('-10$|15$'))


Была ли часть кода, которую я использую для фильтрации дней месяца, я хочу включить
в выводе фрейма данных.

Любая помощь будет очень признательна.

Эдди Лебедки

Что я уже пробовал:

Я запускаю код, как показано выше, и получаю заявленный результат.

1 Ответов

Рейтинг:
2

OriginalGriff

Проанализируйте каждую строку и преобразуйте информацию о дате в datetime — основные типы дат и времени — документация Python 3.8.5[^]
Они должны сортироваться "правильно", где строки сортируются, находя первую другую пару символов и основывая все сравнение на разнице между ними, полностью игнорируя остальную часть строки.


Eddie Winch

Привет OriginalGriff,

Извините, не могли бы вы объяснить, как это сделать ? Я не знаю, где именно изменить код, большое спасибо за вашу помощь.

С уважением

Эдди Лебедки

OriginalGriff

Какой бит доставляет вам проблемы?

Eddie Winch

Я думаю, что мне просто нужно изменить строку кода :- display.sort_values(by=['DATE'])

и или строка кода :- (df3['DATE'].str.содержит('-10$|15$')) чтобы получить нужный мне ответ, не могли бы вы подсказать, что я должен добавить или изменить в этих строках кода, чтобы получить желаемый вывод фрейма данных ?

с уважением

Эдди

OriginalGriff

Прочтите еще раз, что я сказал.

Eddie Winch

Я не уверен, что означает разбор каждой строки, но я должен быть в состоянии преобразовать информацию о дате в datetime.

OriginalGriff

"Разбор" означает просмотр каждой строки и разбиение ее на составные части:
200 RIAT Fairford 15-Jul-2004 D -- SS
Части:
200
РИАТ Фэрфорд
15 июля 2004 года
Д
--
СС

Одна из них - это та часть, которую вы хотите - дата, - поэтому найдите ее (и помните, что второе поле похоже на одно или несколько слов, поэтому вы не можете просто выбрать "слово 3", вы должны быть немного умнее этого.
у вас есть это, вы можете преобразовать его в дату.

Eddie Winch

Привет OriginalGriff,

Я добавил в свой код следующие строки :-

display['DATE'] = pd.to_datetime(display['DATE'])

display = display.sort_values(by='DATE', key=lambda col: 100 * col.dt.day + col.dt.month)

дисплей['дата']= ПД.to_datetime(дисплей['дата']).ДТ.функцию strftime('%г-%В-%Г')

дисплей

А после обновления до последней версии Pandas, которая принимает sort_values с ключевым аргументом, когда я запускаю свой полный код, я получаю нужный мне вывод фрейма данных.

Большое спасибо за вашу помощь ))

с уважением

Эдди Лебедки

OriginalGriff

Всегда пожалуйста!