2016-05-06 3 views
0

Есть ли способ указать индекс DataFrame (строка) на основе совпадающего текста внутри фрейма данных?Python Pandas: найдите индекс, основанный на значении в DataFrame

Я импортирую текстовый файл из Интернета, который находится here каждый день в python pandas DataFrame. Я разбираю только некоторые данные и делаю вычисления, чтобы дать мне пиковое значение для каждого дня. Конкретную группу данных, которую мне нужно собрать, начинается с раздела, озаглавленного «КОМБИНИРОВАННЫЙ ЧАС RTO, ЗАВЕРШИВШИЙ ИНТЕГРИРОВАННЫЙ ПРОГНОЗ ЗАГРУЗКИ MW».

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

Updated as of: 05-05-2016 1700 Constrained operations ARE expected in the AEP, APS, BC, COMED, DOM,and PS zones on 05-06-2016. Constrained operations ARE expected in the AEP, APS, BC, COMED, DOM,and PS zones on 05-07-2016. The PS/ConEd 600/400 MW contract will be limited to 700MW on 05-06-16.

Есть ли способ сопоставить текст в pandas DataFrame и указать индекс этого соответствия? В настоящее время я вручную указываю индекс, который хочу начать с использования переменной «день» ниже на 6-й строке. Я бы хотел, чтобы эта переменная удерживала индекс (строку) кадра данных, который включает текст, который я хочу сопоставить.

ниже код работает, но может перестать работать, если номер строки (индекс) изменения:

def forecastload(): 
    wb = load_workbook(filename = 'pjmactualload.xlsx') 
    ws = wb['PJM Load']  
    printRow = 13 
    #put this in iteration to pull 2 rows of data at a time (one for each day) for 7 days max 
    day = 239 
    while day < 251: 
     #pulls in first day only 
     data = pd.read_csv("http://oasis.pjm.com/doc/projload.txt", skiprows=day, delim_whitespace=True, header=None, nrows=2) 

     #sets data at HE 24 = to data that is in HE 13- so I can delete column 0 data to allow checking 'max' 
     data.at[1,13]= data.at[1,1] 

     #get date for printing it with max load later on 
     newDate = str(data.at[0,0]) 

     #now delete first column to get rid of date data. date already saved as newDate 
     data = data.drop(0,1) 
     data = data.drop(1,1) 

     #pull out max value of day 
     #add index to this for iteration ie dayMax[x] = data.values.max() 
     dayMax = data.max().max() 
     dayMin = data.min().min() 
     #print date and max load for that date 
     actualMax = "Forecast Max" 
     actualMin = "Forecast Min" 
     dayMax = int(dayMax) 
     maxResults = [str(newDate),int(dayMax),actualMax,dayMin,actualMin] 
     d = 1 
     for items in maxResults: 
      ws.cell(row=printRow, column=d).value = items 
      d += 1   
     printRow += 1   
     #print maxResults 
     #l.writerows(maxResults)  
     day = day + 2 
    wb.save('pjmactualload.xlsx') 

ответ

0

В этом случае я рекомендую вам использовать командную строку для того, чтобы получить набор данных, который вы могли бы прочитать позже pandas и делать все, что вы хотите ,

Чтобы получить данные, которые вы можете использовать curl и grep:

$ curl -s http://oasis.pjm.com/doc/projload.txt | grep -A 17 "RTO COMBINED HOUR ENDING INTEGRATED FORECAST" | tail -n +5 
05/06/16 am 68640 66576 65295 65170 66106 70770 77926 83048 84949 85756 86131 86089 
      pm 85418 85285 84579 83762 83562 83289 82451 82460 84009 82771 78420 73258 
05/07/16 am 66809 63994 62420 61640 61848 63403 65736 68489 71850 74183 75403 75529 
      pm 75186 74613 74072 73950 74386 74978 75135 75585 77414 76451 72529 67957 
05/08/16 am 63583 60903 59317 58492 58421 59378 60780 62971 66289 68997 70436 71212 
      pm 71774 71841 71635 71831 72605 73876 74619 75848 78338 77121 72665 67763 
05/09/16 am 63865 61729 60669 60651 62175 66796 74620 79930 81978 83140 84307 84778 
      pm 85112 85562 85568 85484 85766 85924 85487 85737 87366 84987 78666 72166 
05/10/16 am 67581 64686 62968 62364 63400 67603 75311 80515 82655 84252 86078 87120 
      pm 88021 88990 89311 89477 89752 89860 89256 89327 90469 87730 81220 74449 
05/11/16 am 70367 67044 65125 64265 65054 69060 76424 81785 84646 87097 89541 91276 
      pm 92646 93906 94593 94970 95321 95073 93897 93162 93615 90974 84335 77172 
05/12/16 am 71345 67840 65837 64892 65600 69547 76853 82077 84796 87053 89135 90527 
      pm 91495 92351 92583 92473 92541 92053 90818 90241 90750 88135 81816 75042 

Давайте использовать предыдущий вывод (в файле rto.txt) для получения более читаемых данных с использованием awk и sed:

$ awk '/^ [0-9]/{d=$1;print $0;next}{print d,$0}' rto.txt | sed 's/^ //;s/\s\+/,/g' 
05/06/16,am,68640,66576,65295,65170,66106,70770,77926,83048,84949,85756,86131,86089 
05/06/16,pm,85418,85285,84579,83762,83562,83289,82451,82460,84009,82771,78420,73258 
05/07/16,am,66809,63994,62420,61640,61848,63403,65736,68489,71850,74183,75403,75529 
05/07/16,pm,75186,74613,74072,73950,74386,74978,75135,75585,77414,76451,72529,67957 
05/08/16,am,63583,60903,59317,58492,58421,59378,60780,62971,66289,68997,70436,71212 
05/08/16,pm,71774,71841,71635,71831,72605,73876,74619,75848,78338,77121,72665,67763 
05/09/16,am,63865,61729,60669,60651,62175,66796,74620,79930,81978,83140,84307,84778 
05/09/16,pm,85112,85562,85568,85484,85766,85924,85487,85737,87366,84987,78666,72166 
05/10/16,am,67581,64686,62968,62364,63400,67603,75311,80515,82655,84252,86078,87120 
05/10/16,pm,88021,88990,89311,89477,89752,89860,89256,89327,90469,87730,81220,74449 
05/11/16,am,70367,67044,65125,64265,65054,69060,76424,81785,84646,87097,89541,91276 
05/11/16,pm,92646,93906,94593,94970,95321,95073,93897,93162,93615,90974,84335,77172 
05/12/16,am,71345,67840,65837,64892,65600,69547,76853,82077,84796,87053,89135,90527 
05/12/16,pm,91495,92351,92583,92473,92541,92053,90818,90241,90750,88135,81816,75042 

, прочитайте и измените вышеуказанный результат с помощью pandas:

df = pd.read_csv("rto2.txt",names=["date","period"]+list(range(1,13)),index_col=[0,1]) 
df = df.stack().reset_index().rename(columns={"level_2":"hour",0:"value"}) 
df.index = pd.to_datetime(df.apply(lambda x: "{date} {hour}:00 {period}".format(**x),axis=1)) 
df.drop(["date", "hour", "period"], axis=1, inplace=True) 

На данный момент у вас есть прекрасные временные ряды :)

In [10]: df.head() 
Out[10]: 
        value 
2016-05-06 01:00:00 68640 
2016-05-06 02:00:00 66576 
2016-05-06 03:00:00 65295 
2016-05-06 04:00:00 65170 
2016-05-06 05:00:00 66106 

для получения статистики:

In[11]: df.groupby(df.index.date).agg([min,max]) 
Out[11]: 
      value  
       min max 
2016-05-06 65170 86131 
2016-05-07 61640 77414 
2016-05-08 58421 78338 
2016-05-09 60651 87366 
2016-05-10 62364 90469 
2016-05-11 64265 95321 
2016-05-12 64892 92583 

Я надеюсь, что это может помочь вам.

С уважением.

+0

Отлично, спасибо. Это то, что я снимал, но понятия не имел, как туда добраться. Я только слышал о sed и awk и буду проводить с ними некоторое время в эти выходные. Еще раз спасибо. – JLK

+0

Как я это понимаю, следующая строка бросает ошибку при запуске: 'df.index = pd.to_datetime (df.apply (lambda x:" {date} {hour}: 00 {period} ". Format (** x), axis = 1)) 'Ошибка:' KeyError: ('date', u'occurred at index 0 ') ' – JLK

+0

Добро пожаловать. Командная строка - очень мощный инструмент и часто обеспечивает самое простое решение. О, какая у вас ошибка? –

0

Вот как вы можете сделать то, что вы ищете:

enter image description here

И код примера:

import numpy as np 
import pandas a pd 
df = pd.DataFrame(np.random.rand(10,4), columns=list('abcd')) 
df.loc[df['a'] < 0.5, 'a'] = 1 

You can refer to this documentation

Добавлено изображение, показывающее, как получить доступ к индексу:

enter image description here

+0

Я думаю, что мне что-то не хватает, но, используя приведенный выше пример, как определить, какая строка (индекс) содержит 0.249267 из второй таблицы? Как узнать, что это 6? – JLK

+0

Вы можете получить индекс, обратившись к индексу, соответствующему условию типа 'df [df ['a'] <0.5] .index' – Abbas