Вы можете использовать пользовательскую функцию с помощью GroupBy.apply
с next
и iter
для получения первого значения, а при отсутствии совпадения получите NaN
с:
def f(x):
c = next(iter(x.loc[x.Type == "call", 'Price']),np.nan)
p = next(iter(x.loc[x.Type == "put", 'Price']),np.nan)
x['new']= c - p + x.Strike
return x
df = df.groupby(["Expiration","Strike"]).apply(f)
print (df)
Type Price Expiration Strike new
0 put 145.000000 2021-01-15 420.0 NaN
1 call 15.370001 2018-11-30 262.0 275.875001
2 put 1.495000 2018-11-30 262.0 275.875001
3 call 14.930000 2018-11-30 262.5 NaN
Другой решение:
#if possible `call` and `put` are not unique per groups
c = df[df.Type == "call"].groupby(["Expiration","Strike"])['Price'].first()
p = df[df.Type == "put"].groupby(["Expiration","Strike"])['Price'].first()
#if `call` and `put` are unique per groups
#c = df[df.Type == "call"].set_index(["Expiration","Strike"])['Price']
#p = df[df.Type == "put"].set_index(["Expiration","Strike"])['Price']
df1 = df.join((c - p).rename('new'), on=["Expiration","Strike"])
df1['new'] += df1['Strike']
print (df1)
Type Price Expiration Strike new
0 put 145.000000 2021-01-15 420.0 NaN
1 call 15.370001 2018-11-30 262.0 275.875001
2 put 1.495000 2018-11-30 262.0 275.875001
3 call 14.930000 2018-11-30 262.5 NaN
Вам нужно разбить ваш метод DoWork на отчетный прогресс, а затем вызвать ReportProgress.
Возьмем, например, следующее:
private void Something_DoWork(object sender, DoWorkEventArgs e)
{
// If possible, establish how much there is to do
int totalSteps = EstablishWorkload();
for ( int i=0; i<totalSteps; i++)
{
// Do something...
// Report progress, hint: sender is your worker
(sender as BackgroundWorker).ReportProgress((int)(100/totalSteps)*i, null);
}
}
Если ваша работа не может быть определена заранее, попробуйте добавить свой собственные проценты:
private void Something_DoWork(object sender, DoWorkEventArgs e)
{
// some work
(sender as BackgroundWorker).ReportProgress(25, null);
// some work
(sender as BackgroundWorker).ReportProgress(50, null);
// some work
(sender as BackgroundWorker).ReportProgress(60, null);
// some work
(sender as BackgroundWorker).ReportProgress(99, null);
}
Вы должны вручную вызвать ReportProgress ()
, чтобы вызвать событие ProgressChanged .
просто сообщайте о ходе выполнения события dowork
private void _bgwLoadClients_DoWork(object sender, DoWorkEventArgs e) {
int progresValue0to100 = 75;
(sender as System.ComponentModel.BackgroundWorker).ReportProgress(progresValue0to100);
//do your jobs..
}
это работает так
Прогресс должен отправляться из события DoWork с помощью вызов метода ReportProgress в BackgroundWorker. В вашем случае вы можете ' • сообщать о любом прогрессе, потому что вся работа выполняется вне функции DoWork. Вы можете сообщать о ходе выполнения только до и после вызова getdate (), но не во время вызова, поскольку поток BackgroundWorker занят.
Вам нужно вызвать worker.ReportProgress (percentComplete) в вашем методе DoWork. процентComplete следует вычислять на основе общей работы. Например:
for(int i =0; i != 100; i++) {
// do something
worker.ReportProgress(i);
}
Иногда бывает сложно разделить задание на несколько частей, чтобы можно было сообщать о ходе выполнения. К сожалению, BackgroundWorker не решает эту проблему, вам придется сделать это самостоятельно.