Среднее значение только двух последовательных строк с условными выражениями - PullRequest
0 голосов
/ 13 сентября 2018

После поиска похожих вопросов я узнал с этим и этим вопросами. К сожалению, ни один из них не работает со мной.

Первый работает на всех столбцах, второй не работает на моих столбцах True и False и возвращает ошибку (я также не полностью ее понял).

Вот описание проблемы:

Я работаю с фреймом данных ~ 54k строк. Вот пример 24 значений:

+----+---------------------+---------------------+----------------------+--------------------+-------+
|    |        date         |       omegasr       |        omega         |      omegass       | isday |
+----+---------------------+---------------------+----------------------+--------------------+-------+
|  1 | 2012-03-27 00:00:00 | -1.5707963267948966 |    -3.32335035194977 | 1.5707963267948966 | False |
|  2 | 2012-03-27 01:00:00 | -1.5707963267948966 |  -3.0615509641506207 | 1.5707963267948966 | False |
|  3 | 2012-03-27 02:00:00 | -1.5707963267948966 |   -2.799751576351471 | 1.5707963267948966 | False |
|  4 | 2012-03-27 03:00:00 | -1.5707963267948966 |  -2.5379521885523215 | 1.5707963267948966 | False |
|  5 | 2012-03-27 04:00:00 | -1.5707963267948966 |  -2.2761528007531724 | 1.5707963267948966 | False |
|  6 | 2012-03-27 05:00:00 | -1.5707963267948966 |   -2.014353412954023 | 1.5707963267948966 | False |
|  7 | 2012-03-27 06:00:00 | -1.5707963267948966 |  -1.7525540251548732 | 1.5707963267948966 | False |
|  8 | 2012-03-27 07:00:00 | -1.5707963267948966 |  -1.4907546373557239 | 1.5707963267948966 | True  |
|  9 | 2012-03-27 08:00:00 | -1.5707963267948966 |  -1.2289552495565745 | 1.5707963267948966 | True  |
| 10 | 2012-03-27 09:00:00 | -1.5707963267948966 |  -0.9671558617574253 | 1.5707963267948966 | True  |
| 11 | 2012-03-27 10:00:00 | -1.5707963267948966 |  -0.7053564739582756 | 1.5707963267948966 | True  |
| 12 | 2012-03-27 11:00:00 | -1.5707963267948966 | -0.44355708615912615 | 1.5707963267948966 | True  |
| 13 | 2012-03-27 12:00:00 | -1.5707963267948966 |  -0.1817576983599767 | 1.5707963267948966 | True  |
| 14 | 2012-03-27 13:00:00 | -1.5707963267948966 |  0.08004168943917273 | 1.5707963267948966 | True  |
| 15 | 2012-03-27 14:00:00 | -1.5707963267948966 |  0.34184107723832213 | 1.5707963267948966 | True  |
| 16 | 2012-03-27 15:00:00 | -1.5707963267948966 |   0.6036404650374716 | 1.5707963267948966 | True  |
| 17 | 2012-03-27 16:00:00 | -1.5707963267948966 |   0.8654398528366211 | 1.5707963267948966 | True  |
| 18 | 2012-03-27 17:00:00 | -1.5707963267948966 |    1.127239240635771 | 1.5707963267948966 | True  |
| 19 | 2012-03-27 18:00:00 | -1.5707963267948966 |   1.3890386284349199 | 1.5707963267948966 | True  |
| 20 | 2012-03-27 19:00:00 | -1.5707963267948966 |   1.6508380162340692 | 1.5707963267948966 | False |
| 21 | 2012-03-27 20:00:00 | -1.5707963267948966 |   1.9126374040332188 | 1.5707963267948966 | False |
| 22 | 2012-03-27 21:00:00 | -1.5707963267948966 |    2.174436791832368 | 1.5707963267948966 | False |
| 23 | 2012-03-27 22:00:00 | -1.5707963267948966 |   2.4362361796315177 | 1.5707963267948966 | False |
| 24 | 2012-03-27 23:00:00 | -1.5707963267948966 |    2.698035567430667 | 1.5707963267948966 | False |
+----+---------------------+---------------------+----------------------+--------------------+-------+

omega - угол солнечного часа в радианах. Диапазон значений от -pi / 2 до + pi / 2 для часов 00:00 и 24:00 соответственно. В полдень его значение равно 0.

omegass - часовой угол, под которым происходит закат. Из-за симметрии солнечно-земной системы omegasr = -omegass. Эти значения постоянны в течение одного дня, но меняются для каждого дня.

Столбец isday является результатом условного выражения: когда omegasr < omega < omegasr, то это день и могут быть сделаны дальнейшие вычисления.

Чтобы выполнить дальнейшие вычисления, мне нужно привязать для каждого часа среднюю точку промежутка времени, который охватывает мера. Так, например, показатель полудня был записан в 12:00, но для того, чтобы представить весь этот час, я хочу иметь часовой угол 12:30. Поэтому мне нужно

omegam[i] = (omega[i],omega[i+1]).mean() 

, где i представляет индекс.

Но здесь возникает новая проблема: если закат происходит, скажем, в 6:40 утра, то час средней точки должен быть рассчитан следующим образом:

omegam[i] = (omegasr[i],omega[i+1]).mean() #sunrise
omegam[i] = (omega[i],omegass[i+1]).mean() #sunset

Таким образом, часовой радианный угол будет соответствовать 6:50 утра. Я создал столбец isday, чтобы помочь выполнить эту задачу, но, к сожалению, я не могу его использовать.

Спасибо.

РЕДАКТИРОВАТЬ:

Решение, предложенное @Mabel Villaba, неверно, поскольку столбец new_omega имеет только значения восхода и захода солнца.

Прямой столбец new_omega будет:

 new_omega  
... 
7   #here the mean is between omegasr and omega[8], therefore this new_omega value can't have a correct value, according to the proposed solution.

8   -1.2289552495565745 # = omega[9]       
9   omega[10]  #                  
10  omega[11]
... 
17   omega[18] 
18   omega[19] 
19   1.570796  #omegass
...

Я надеюсь, что это достаточно ясно

EDIT2:

Еще раз спасибо, но значения все еще не верны: средние значения по-прежнему рассчитываются неправильно. Я рассчитал вручную правильные значения, выложу их здесь:

     omegam

...
7    -1.530775
8    -1.359855
9    -1.098058
...
13   -0.05256705
...
19   1.47992
...

EDIT3:

Я думаю, что столбец df['isday'], полученный благодаря логической маске, может вводить в заблуждение.

Фактически: восход солнца всегда происходит между двумя рядами, пусть они называются omega1 и omega2, которые принадлежат row1 и row2 соответственно. То же самое происходит с закатом, но с omega3 и omega4. Что происходит, так это то, что правильный omegam из row1 вычисляется как:

omegam(row1) = (omegasr + omega2)/2

, но row1 имеет атрибут False в столбце isday.

Для заката все наоборот: встречается между row3 и row4 и рассчитывается как:

omegam(row3) = (omega3 + omegass)/2

и row3 имеет атрибут True.

1 Ответ

0 голосов
/ 13 сентября 2018

РЕДАКТИРОВАТЬ

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

Давайте создадим два омеги, omega1, которые omegam[i] = 0.5 * (omega[i] + omegasr[i+1]), и еще один omega2, которые omegam[i] = 0.5 * (omega[i-1] + omegass[i]):

df['omega1'] = .5*((df['omega'] + df['omegasr'].shift(-1)))   
df['omega2'] = .5*((df['omega'].shift(1) + df['omegass']))

Затем нам нужно создать маску, которая сообщает нам, является ли это закатом или восходом солнца, или ни одной из них:

df['mask'] =  (df['isday'] * 1).diff().bfill()

>> df[['date','mask', 'isday']]

                     date  mask  isday
0    2012-03-27 00:00:00    0.0  False
1    2012-03-27 01:00:00    0.0  False
2    2012-03-27 02:00:00    0.0  False
3    2012-03-27 03:00:00    0.0  False
4    2012-03-27 04:00:00    0.0  False
5    2012-03-27 05:00:00    0.0  False
6    2012-03-27 06:00:00    0.0  False
7    2012-03-27 07:00:00    1.0   True
8    2012-03-27 08:00:00    0.0   True
9    2012-03-27 09:00:00    0.0   True
10   2012-03-27 10:00:00    0.0   True
11   2012-03-27 11:00:00    0.0   True
12   2012-03-27 12:00:00    0.0   True
13   2012-03-27 13:00:00    0.0   True
14   2012-03-27 14:00:00    0.0   True
15   2012-03-27 15:00:00    0.0   True
16   2012-03-27 16:00:00    0.0   True
17   2012-03-27 17:00:00    0.0   True
18   2012-03-27 18:00:00    0.0   True
19   2012-03-27 19:00:00   -1.0  False
20   2012-03-27 20:00:00    0.0  False
21   2012-03-27 21:00:00    0.0  False
22   2012-03-27 22:00:00    0.0  False
23   2012-03-27 23:00:00    0.0  False

Таким образом, df['mask']==1 соответствуетдо восхода солнца, df['mask']==-1 до заката и df['mask']==0 соответствует отдыху.

На основании этих условий мы можем создать omegam:

df['omegam'] = df['omega'].rolling(2).mean() * (df['mask'] == 0) + \
               df['omega1'] * (df['mask']==1) + \
               df['omega2'] * (df['mask']==-1)

>> df[['date','omegam']]

                     date    omegam
0    2012-03-27 00:00:00        NaN
1    2012-03-27 01:00:00  -3.192451
2    2012-03-27 02:00:00  -2.930651
3    2012-03-27 03:00:00  -2.668852
4    2012-03-27 04:00:00  -2.407052
5    2012-03-27 05:00:00  -2.145253
6    2012-03-27 06:00:00  -1.883454
7    2012-03-27 07:00:00  -1.530775
8    2012-03-27 08:00:00  -1.359855
9    2012-03-27 09:00:00  -1.098056
10   2012-03-27 10:00:00  -0.836256
11   2012-03-27 11:00:00  -0.574457
12   2012-03-27 12:00:00  -0.312657
13   2012-03-27 13:00:00  -0.050858
14   2012-03-27 14:00:00   0.210941
15   2012-03-27 15:00:00   0.472741
16   2012-03-27 16:00:00   0.734540
17   2012-03-27 17:00:00   0.996340
18   2012-03-27 18:00:00   1.258139
19   2012-03-27 19:00:00   1.479917
20   2012-03-27 20:00:00   1.781738
21   2012-03-27 21:00:00   2.043537
22   2012-03-27 22:00:00   2.305336
23   2012-03-27 23:00:00        NaN

СТАРЫЕ РЕШЕНИЯ :

Как вы упомянули, начиная с omegasr = -omegass, вы можете создать новый столбец в ваших пандах в зависимости от часа, чтобы вы могли получить omega, что вам нужно для средней операции (если восходчас <12): omegasr, иначе: - omegasr): </p>

df['new_omega'] = df.apply(lambda x: x['omegasr'] if pd.to_datetime(x['date']).hour < 12 else -x['omegasr'], axis=1).shift(-1)

>> df

                     date   omegasr     omega   omegass  isday  new_omega

1    2012-03-27 00:00:00  -1.570796 -3.323350  1.570796  False  -1.570796
2    2012-03-27 01:00:00  -1.570796 -3.061551  1.570796  False  -1.570796
3    2012-03-27 02:00:00  -1.570796 -2.799752  1.570796  False  -1.570796
4    2012-03-27 03:00:00  -1.570796 -2.537952  1.570796  False  -1.570796
5    2012-03-27 04:00:00  -1.570796 -2.276153  1.570796  False  -1.570796
6    2012-03-27 05:00:00  -1.570796 -2.014353  1.570796  False  -1.570796
7    2012-03-27 06:00:00  -1.570796 -1.752554  1.570796  False  -1.570796
8    2012-03-27 07:00:00  -1.570796 -1.490755  1.570796   True  -1.570796
9    2012-03-27 08:00:00  -1.570796 -1.228955  1.570796   True  -1.570796
10   2012-03-27 09:00:00  -1.570796 -0.967156  1.570796   True  -1.570796
11   2012-03-27 10:00:00  -1.570796 -0.705356  1.570796   True  -1.570796
12   2012-03-27 11:00:00  -1.570796 -0.443557  1.570796   True   1.570796
13   2012-03-27 12:00:00  -1.570796 -0.181758  1.570796   True   1.570796
14   2012-03-27 13:00:00  -1.570796  0.080042  1.570796   True   1.570796
15   2012-03-27 14:00:00  -1.570796  0.341841  1.570796   True   1.570796
16   2012-03-27 15:00:00  -1.570796  0.603640  1.570796   True   1.570796
17   2012-03-27 16:00:00  -1.570796  0.865440  1.570796   True   1.570796
18   2012-03-27 17:00:00  -1.570796  1.127239  1.570796   True   1.570796
19   2012-03-27 18:00:00  -1.570796  1.389039  1.570796   True   1.570796
20   2012-03-27 19:00:00  -1.570796  1.650838  1.570796  False   1.570796
21   2012-03-27 20:00:00  -1.570796  1.912637  1.570796  False   1.570796
22   2012-03-27 21:00:00  -1.570796  2.174437  1.570796  False   1.570796
23   2012-03-27 22:00:00  -1.570796  2.436236  1.570796  False   1.570796
24   2012-03-27 23:00:00  -1.570796  2.698036  1.570796  False        NaN

Данные в 'new_omega' сдвигаются в соответствии с

omegam[i] = (omegasr[i],omega[i+1]).mean() #sunrise
omegam[i] = (omega[i],omegass[i+1]).mean() #sunset

Тогда omegam можно получить простоприменяя среднее значение к столбцам omega и new_omega, когда выполняется условие df['isday']==True, или mean(omega[i], omega[i+1]), когда df['isday']==False:

# Calculate the rolling mean with a window=2 and then shift backwards 
# (by default pd.rollling(2).mean() would result in 
# omegam[i]= mean(omega[i-1], omega[i]))


df['omegam'] = df['omega'].rolling(2).mean().shift(-1)


df['omegam'][df['isday']] = df[['omega', 'new_omega']][df['isday']].mean(axis=1).values

>> df['omegam']

1    -3.192451
2    -2.930651
3    -2.668852
4    -2.407052
5    -2.145253
6    -1.883454
7    -1.621654
8    -1.530775
9    -1.399876
10   -1.268976
11   -1.138076
12    0.563620
13    0.694519
14    0.825419
15    0.956319
16    1.087218
17    1.218118
18    1.349018
19    1.479917
20    1.781738
21    2.043537
22    2.305336
23    2.567136
24         NaN
Name: omegam, dtype: float64

Надеюсь, это подойдет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...