我的数据框如下所示:
scale cons hold supply add.supply s_res z_res
48 -5 NaN NaN NaN NaN NaN NaN
49 -4 NaN NaN NaN NaN NaN NaN
50 -3 NaN NaN NaN NaN NaN NaN
51 -2 NaN NaN NaN NaN NaN NaN
52 -1 NaN NaN NaN NaN NaN NaN
53 0 0 300 0 NaN 100 200
54 1 20 NaN 0 NaN 200 322
55 2 30 NaN 70 NaN 100 100
56 3 25 NaN 0 NaN 400 110
57 4 15 NaN 0 NaN 100 300
58 5 10 NaN 0 NaN 100 180
59 6 40 NaN 0 NaN 100 100
...
我需要做以下事情:
从scale = 1
填充列hold
的值开始,其值按如下方式计算:
我从列hold
中取出先前的值,并从列cons
中减去当前单元格的相应值,并从列supply
中添加相应的值。
(对于与hold
对应的列scale = 1
中的单元格,它将为(300 - 20) + 0 = 280
,
下一个单元格(280 - 30) + 70) = 320
,下一个单元格(320 - 25) + 0) = 295
等等
如果列hold
中的值小于列s_res
中的对应值,则对于下一个单元格,我必须在列{{{}}中添加相应的下一个单元格值之间的差异1}}和s_res
。
例如,列z_res
中的值为hold
,其中295
。该值小于列scale = 3
中的值。然后我需要计算下一个值:s_res = 400
。并在(295 - 15) + 0 + (300 - 100) = 480
列中的s_res
和z_res
之间写下这种区别。
我需要列add.supply
中的每个新计算值检查它是否小于hold
列中的值。
结果应如下所示:
s_res
我很感激任何建议。
UPD 我尝试应用代码
scale cons hold supply add.supply s_res z_res
48 -5 NaN NaN NaN NaN NaN NaN
49 -4 NaN NaN NaN NaN NaN NaN
50 -3 NaN NaN NaN NaN NaN NaN
51 -2 NaN NaN NaN NaN NaN NaN
52 -1 NaN NaN NaN NaN NaN NaN
53 0 0 300 0 NaN 100 200
54 1 20 280 0 NaN 200 322
55 2 30 320 70 NaN 100 100
56 3 25 295 0 NaN 400 110
57 4 15 480 0 200 100 300
58 5 10 470 0 NaN 100 180
59 6 40 430 0 NaN 100 100
...
更大的数据框,我遇到了问题
我的新数据框
df['hold'] = df.hold.fillna(method='ffill') - df.cons.cumsum() + df.supply.cumsum()
df['add.supply'] = np.where(df.hold.shift() < df.s_res.shift(), df.z_res - df.s_res, np.nan)
df['hold'] = df.hold + df['add.supply'].fillna(0).cumsum()
结果应如下:
scale cons hold supply add.supply s_res z_res
0 0 0 300 0 NaN 100 200
1 1 20 NaN 0 NaN 200 322
2 2 30 NaN 70 NaN 100 100
3 3 25 NaN 0 NaN 400 110
4 4 15 NaN 0 NaN 100 300
5 5 10 NaN 0 NaN 100 180
6 6 40 NaN 0 NaN 100 100
7 7 60 NaN 0 NaN 300 400
8 8 50 NaN 0 NaN 245 300
9 9 70 NaN 0 NaN 300 600
10 10 50 NaN 0 NaN 143 228
...
但代码执行的结果并非如此:
scale cons hold supply add.supply s_res z_res
0 0 0 300 0 NaN 100 200
1 1 20 280 0 NaN 200 322
2 2 30 320 70 NaN 100 100
3 3 25 295 0 NaN 400 110
4 4 15 480 0 200 100 300
5 5 10 470 0 NaN 100 180
6 6 40 430 0 NaN 100 100
7 7 60 370 0 NaN 300 400
8 8 50 320 0 NaN 245 300
9 9 70 250 0 NaN 300 600
10 10 50 285 0 85 143 228
...
scale cons hold supply add.supply s_res z_res
0 0 0 300 0 NaN 100 200
1 1 20 280 0 NaN 200 322
2 2 30 320 70 NaN 100 100
3 3 25 295 0 NaN 400 110
4 4 15 480 0 200 100 300
5 5 10 470 0 NaN 100 180
6 6 40 430 0 NaN 100 100
7 7 60 370 0 NaN 300 400
8 8 50 375 0 55 245 300
9 9 70 605 0 300 300 600
10 10 50 640 0 85 143 228
...
后出现错误,但我不明白为什么。
答案 0 :(得分:2)
您可以使用cumsum()
和np.where
的组合在整个DataFrame中执行此操作,而不是逐行执行此操作:
df['hold'] = df.hold.fillna(method='ffill') - df.cons.cumsum() + df.supply.cumsum()
df['add.supply'] = np.where(df.hold.shift() < df.s_res.shift(), df.z_res - df.s_res, np.nan)
df['hold'] = df.hold + df['add.supply'].fillna(0).cumsum()
想想你想分两个阶段做的转变。您有一个初始阶段,您正在添加和减去初始值df.hold
。然后,根据某些条件,你在某些情况下改变了新的持有价值。
cumsum()
采用Series或DataFrame并创建一个新版本,其中每一行是前一行和当前行的累积和。您可以对df.cons
和df.supply
执行此操作,以获取将从df.hold
中扣除并添加到df.hold
的累计金额。现在您已经计算了np.where
的第一阶段。
您可以使用df.hold
查找df['add.supply']
何时符合您感兴趣的条件。如果符合您的条件,您可以相应地设置df.hold
。然后,您可以将此新列添加到fillna(0)
。请注意,我们使用cumsum()
确保每一行都有一个值,并再次使用add.supply
来保留添加的条件值。
<强>更新强>
上面的原始代码在添加一个df.hold
值后无效,因为df['hold'] = df.hold.fillna(method='ffill') - df.cons.cumsum() + df.supply.cumsum()
hold = df.hold.tolist()
s_res = df.s_res.tolist()
add = (df.z_res - df.s_res).shift(-1).tolist()
newh = [hold[0]]
totala = 0
for h, s, a in zip(hold, s_res, add):
newh.append(h + totala)
if newh[-1] < s:
totala += a
df['hold'] = pd.Series(newh[1:])
df['add.supply'] = np.where(df.hold.shift() < df.s_res.shift(), df.z_res - df.s_res, np.nan)
的第一阶段的未来值尚未包含它。可能有一种方法可以非迭代地执行此操作,并且肯定比我在下面所做的更好更清洁,但这至少可以完成工作:
function multiRequest($data, $options = array()) {
// array of curl handles
$curly = array();
// data to be returned
$result = array();
// multi handle
$mh = curl_multi_init();
// loop through $data and create curl handles
// then add them to the multi-handle
foreach ($data as $id => $d) {
$curly[$id] = curl_init();
$url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;
curl_setopt($curly[$id], CURLOPT_URL, $url);
curl_setopt($curly[$id], CURLOPT_HEADER, 0);
curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);
// post?
if (is_array($d)) {
if (!empty($d['post'])) {
curl_setopt($curly[$id], CURLOPT_POST, 1);
curl_setopt($curly[$id], CURLOPT_POSTFIELDS, $d['post']);
}
}
// extra options?
if (!empty($options)) {
curl_setopt_array($curly[$id], $options);
}
curl_multi_add_handle($mh, $curly[$id]);
}
// execute the handles
$running = null;
do {
curl_multi_exec($mh, $running);
} while($running > 0);
// get content and remove handles
foreach($curly as $id => $c) {
$result[$id] = curl_multi_getcontent($c);
curl_multi_remove_handle($mh, $c);
}
// all done
curl_multi_close($mh);
return $result;
}