13

次のような pandas データフレームがあるとします。

  cat  val
0   a    1
1   a    6
2   a   12
3   b    2
4   b    5
5   b   11
6   c    4
7   c   22

そして、各カテゴリ(「猫」の各値)について、値が特定の値に最も近い位置、たとえば5.5を知りたいです。目標値を差し引いて絶対値を取ると、次のようになります。

  cat  val  val_delt
0   a    1       4.5
1   a    6       0.5
2   a   12       6.5
3   b    2       3.5
4   b    5       0.5
5   b   11       5.5
6   c    4       1.5
7   c   22      16.5

しかし、次はどこに行こうか迷っています。私の最初の考えは、groupby() で argmin() を使用することでしたが、これはエラーになります:

In [375]: df.groupby('cat').val_delt.argmin()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-375-a2c3dbc43c50> in <module>()
----> 1 df.groupby('cat').val_delt.argmin()

TypeError: 'Series' object is not callable

もちろん、標準の python で、cat のすべての値を反復処理し、その値に対応するデータのサブセットを選択し、argmin 操作を実行して、元のデータフレームのどこに行でした。しかし、これを行うにはもっとエレガントな方法が必要です。

出力として欲しいのは、次のようなものです。

  cat  val
1   a    6      
4   b    5       
6   c    4  

または少なくともその関連情報を含む何らかの構造 (例 - {'a':1, 'b':4, 'c':6} )。インデックス値またはインデックス位置を取得するかどうかは気にしませんが、2 つのうちの 1 つが必要です。値を取得することは気にしません。インデックス サブセットを取得したら、後でいつでも値を取得できます。

4

5 に答える 5

6

argmin()は agg 関数ではありません。apply を使用して、すべてのグループの最も近いインデックスを取得できます。

txt = """  cat  val
0   a    1
1   a    6
2   a   12
3   b    2
4   b    5
5   b   11
6   c    4
7   c   22"""

import io

df = pd.read_csv(io.BytesIO(txt), delim_whitespace=True, index_col=0)
df["val_delt"] = (df.val - 5.5).abs()
idx = df.groupby("cat").apply(lambda df:df.val_delt.argmin())
df.ix[idx, :]

出力:

cat  val  val_delt
1   a    6       0.5
4   b    5       0.5
6   c    4       1.5
于 2013-10-29T01:39:53.780 に答える
4

HYRY の回答に追加するだけで、idxmin を使用できます。例:

import io
txt = """  cat  val
0   a    1
1   a    6
2   a   12
3   b    2
4   b    5
5   b   11
6   c    4
7   c   22"""
df = pd.read_csv(io.BytesIO(txt.encode()), delim_whitespace=True, index_col=0)
df["val_delt"] = (df.val - 5.5).abs()
idx = df.groupby("cat").apply(lambda df:df.val_delt.idxmin())
df.ix[idx, :]
于 2015-04-13T13:11:49.717 に答える