パンダでさまざまな間隔でバイアスされた1つの列を別の列からグループ化するにはどうすればよいですか?
Dec 12 2020
私は次のpd.DataFrameを持っています:
source = pd.DataFrame([[0.99, 0.98, 0.93, 0.81, 0.85, 0.71, 0.7, 0.69, 0.68, 0.66],
[100, 12, 312, 23, 2, 12, 32, 21, 21, 21]]).T
できるだけ早く次のように変換したいと思います。
desired_result = pd.DataFrame([[0.9, 0.8, 0.7, 0.6], [424, 25, 44, 63]]).T
上記の場合、データフレームの0.1
列に適用する間隔を定義し、同じデータフレームの列を合計します。アイデアは、これが異なる間隔で機能するはずであるということです。0
source
1
私が試したこと:
使うことを考えました
pd.cut
が、それは私が探しているものではないようです。source
対応する行に0.9、0.8、0.7、0.6の重複値がある新しい列を追加するとgroupby
、この新しい列で使用できることを知っていますsum
が、よりクリーンで迅速な方法があるかどうか疑問に思っていますこれをする?例:このようなsmth:
interval = 0.1
source['ints'] = (source[0] / interval).astype(int)
result = source.groupby(source['ints']).sum().reset_index()
result
ただし、たとえば間隔を0.1から0.05に変更した場合、上記は機能しません。
どんな助けでもいただければ幸いです。
回答
3 PierreD Dec 12 2020 at 21:28
スピードのために:常にあなたができるすべてをベクトル化するようにしてください、そしてできるだけ避けてください apply
。
これがより速い方法です(@DavidEricksonのクレジットsort=False
):
interval = 0.1
source.groupby(np.trunc(source[0] / interval) * interval, sort=False)[1].sum().reset_index()
# out:
0 1
0 0.9 424.0
1 0.8 25.0
2 0.7 12.0
3 0.6 95.0
速度差は、大きい場合は非常に劇的になる可能性がありdf
ます。
10Kのビンにグループ化された100万行で試してください。
source = pd.DataFrame(np.random.normal(scale=1000, size=(int(1e6), 2)))
%%timeit
# ... (as above)
26.7 ms ± 292 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
apply
代わりに:
1.51 s ± 11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
(50倍遅い)。
1 DavidErickson Dec 12 2020 at 20:55
custom_round
私が3つの変更を加えた関数を使用できますhttps://stackoverflow.com/a/40372261/6366770:
- 降りたいので
np.floor
代わりに使いましround
た。 - これにより、ビンの「境界」にある値が台無しになるため、境界のすぐ上にあり、正しく切り捨てられるように追加します
+ base/100
(つまり、0.8に誤ってではなく.9に切り捨てられ0.9
ます0.9 + .009 = 0.909
)。これでカバーできると思います。あなたは1 / 1000
安全のためにできる。 - 私が共有する答えは探していた
int
のでint
、丸みを帯びたフロートを見ているので削除されました
source = pd.DataFrame(np.random.normal(scale=1000, size=(int(1e6), 2)))
def custom_round(x, y, base):
return source.groupby((base * np.floor((x + (base / 100)) / base)), sort=False)[y].sum()
%timeit custom_round(source[0], 1, .1)
89.8 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
私のコンピューターでは、受け入れられた答えは遅いです:
102 ms ± 1.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)