初心者です。Pythonを使って以下のようなForループを使って計算をしているのですが、データが大量にあるので計算に非常に時間がかかります。
この計算を早くするにはどのようにコードを変えれば良いでしょうか。もっと上手い計算方法があるような気がするのですが。。
よろしくお願いします。
Python
1for (wcolumn, zcolumn) in zip(W_columns, Z_columns): 2 afterdf2[wcolumn] = 0.0 3 for date1 in dates: 4 for name1 in sector_names: 5 z20sum = afterdf2[(afterdf2.DATE == date1) & (afterdf2.SECTOR == name1) & (afterdf2[zcolumn] >= np.percentile(afterdf2[(afterdf2.DATE == date1) & (afterdf2.SECTOR == name1)].ix[:, zcolumn],80))].ix[:,zcolumn].sum() 6 afterdf2[wcolumn] = np.where((afterdf2.DATE == date1) & (afterdf2.SECTOR == name1) & (afterdf2[zcolumn] >= np.percentile(afterdf2[(afterdf2.DATE == date1) & (afterdf2.SECTOR == name1)].ix[:, zcolumn],80)), afterdf2[zcolumn] / z20sum * afterdf2['Sectorweight'] , afterdf2[wcolumn] ) 7
式がややこしいですが、dates, sector_namesの要素ごとに、zcolumnが上位2割の数値を取り出して計算してafterdf2[wcolumn]というところに数値を返しています。
【上記と似たコードですが追加で質問です】
上記については、教えて頂いた通りにgroupby, transform, np.whereを組み合わせることで計算時間が数十分の1に改善しました。ありがとうございます。
他のコードも同様に修正できたのですが、どうしても以下のコードが修正できません。上記のコードとほぼ一緒で、DATE, SECTORでgroupby()をするというところまでは同じだと思うのですが、zcolumnの上位20%の行のMKT_CAPという列の数字を操作するところが違い上手くいきません。
Python
1for (wcolumn, zcolumn) in zip(WM_columns, Z_columns): 2 afterdf2[wcolumn] = 0.0 3 for date1 in dates: 4 for name1 in sector_names: 5 z20sum = afterdf2[(afterdf2.DATE == date1) & (afterdf2.SECTOR == name1) & (afterdf2[zcolumn] >= np.percentile(afterdf2[(afterdf2.DATE == date1) & (afterdf2.SECTOR == name1)].ix[:, zcolumn],80))].ix[:,'MKT_CAP'].sum() 6 afterdf2[wcolumn] = np.where((afterdf2.DATE == date1) & (afterdf2.SECTOR == name1) & (afterdf2[zcolumn] >= np.percentile(afterdf2[(afterdf2.DATE == date1) & (afterdf2.SECTOR == name1)].ix[:, zcolumn],80)), afterdf2['MKT_CAP'] / z20sum * afterdf2['Sectorweight'] , afterdf2[wcolumn] )
教えて頂いたコードを参考に以下のように直してみたのですが、文法的に間違っているのか、TypeError: Transform function invalid for data typesというエラーになります。もし解決法がお分かりでしたら教えて頂けると大変助かります。よろしくお願いします。
Python
1afterdf2.groupby(['DATE','SECTOR'])[[zcolumn,'MKT_CAP']].transform(lambda d,m : np.where(d >= d.quantile(0.8), m / m[d >= d.quantile(0.8)].sum(), 0))
回答2件
あなたの回答
tips
プレビュー