获取数据框中分类变量的最小值和最大值

Iro*_*den 17 python aggregate pandas

我有一个如下所示的数据框:

D   X   Y   Z
A  22  16  23
A  21  16  22
A  20  17  21
B  33  50  11
B  34  53  12
B  34  55  13
C  44  34  11
C  45  33  11
C  45  33  10
D  55  35  60
D  57  34  61
E  66  36  13
E  67  38  14 
E  67  37  13
Run Code Online (Sandbox Code Playgroud)

我想获取所有列值中分类变量的最小值和最大值D,因此输出数据框应如下所示:

D Xmin Xmax Ymin Ymax Zmin Zmax
A 20    22   16   17   21   23 
B 33    34   50   55   11   13    
C 44    45   33   34   10   11  
D 55    57   34   35   60   61
E 66    67   36   38   13   14
Run Code Online (Sandbox Code Playgroud)

我已经尝试过这个,但没有运气:

min_max_df = dfObj.groupby('D').agg({'X': [dfObj.min(axis=0), dfObj.max(axis=0)]})
Run Code Online (Sandbox Code Playgroud)

小智 13

df = df.groupby('D').agg(['min', 'max'])
Run Code Online (Sandbox Code Playgroud)

输出:

>>> df
    X       Y       Z    
  min max min max min max
D                        
A  20  22  16  17  21  23
B  33  34  50  55  11  13
C  44  45  33  34  10  11
D  55  57  34  35  60  61
E  66  67  36  38  13  14

>>> df['X']['min']
D
A    20
B    33
C    44
D    55
E    66
Name: min, dtype: int64
Run Code Online (Sandbox Code Playgroud)

您也可以展平列:

df.columns = df.columns.map(''.join)
df.rename_axis(None)

   Xmin  Xmax  Ymin  Ymax  Zmin  Zmax
A    20    22    16    17    21    23
B    33    34    50    55    11    13
C    44    45    33    34    10    11
D    55    57    34    35    60    61
E    66    67    36    38    13    14
Run Code Online (Sandbox Code Playgroud)


Asi*_* M. 10

from itertools import product
aggs = {f"{col}{fn}": (col, fn) for col,fn in product(['X', 'Y', 'Z'], ['min', 'max'])}
df.groupby('D').agg(**aggs)
>>>
   Xmin  Xmax  Ymin  Ymax  Zmin  Zmax
D
A    20    22    16    17    21    23
B    33    34    50    55    11    13
C    44    45    33    34    10    11
D    55    57    34    35    60    61
E    66    67    36    38    13    14
Run Code Online (Sandbox Code Playgroud)


Iva*_*sky 9

我相信这是一种很好的方法,并且只需一行代码即可。利用join 通过索引和and进行运算来区分最小值和最大值。rsuffixlsuffix

output = df.groupby('D').min().join(df.groupby('D').max(), lsuffix='min', rsuffix='max')
Run Code Online (Sandbox Code Playgroud)

输出:

   Xmin  Xmax  Ymin  Ymax  Zmin  Zmax
D
A    20    22    16    17    21    23
B    33    34    50    55    11    13
C    44    45    33    34    10    11
D    55    57    34    35    60    61
E    66    67    36    38    13    14
Run Code Online (Sandbox Code Playgroud)


Rod*_*alm 7

df = df.groupby('D').agg(['min', 'max'])\ndf.columns = df.columns.map("".join)  # flatten multi-level columns\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
>>> df\n\n   Xmin  Xmax  Ymin  Ymax  Zmin  Zmax\nD                                    \nA    20    22    16    17    21    23\nB    33    34    50    55    11    13\nC    44    45    33    34    10    11\nD    55    57    34    35    60    61\nE    66    67    36    38    13    14\n
Run Code Online (Sandbox Code Playgroud)\n

速度测试

\n

我做了一些简单的测试,比较了 Celius、Asish 和 user17242583/我的解决方案。

\n

设置

\n
import numpy as np \nimport pandas as pd \nfrom itertools import product\n\nn = 1_000_000\nrng = np.random.default_rng() \n\ndf = pd.DataFrame({\n    'D': rng.choice(list("ABCDEFGH"), size=n),\n    'X': rng.integers(100, size=n),\n    'Y': rng.integers(100, size=n),\n    'Z': rng.integers(100, size=n),\n})\n\n>>> df.shape\n(1000000, 4)\n
Run Code Online (Sandbox Code Playgroud)\n

结果

\n

这是结果。

\n
# Ashish's \n>>> %%timeit -n 50\n... aggs = {f"{col}{fn}": (col, fn) for col,fn in product(['X', 'Y', 'Z'], ['min', 'max'])}\n... df1 = df.groupby('D').agg(**aggs) \n\n116 ms \xc2\xb1 5.88 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 50 loops each)\n\n# user17242583's / mine \n>>> %%timeit -n 50\n... df1 = df.groupby('D').agg(['min', 'max'])\n... df1.columns = df1.columns.map("".join)  # flat multi-level columns\n\n120 ms \xc2\xb1 4.69 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 50 loops each)\n\n#Celius's\n>>> %%timeit -n 50\n... df1 = df.groupby('D').min().join(df.groupby('D').max(), lsuffix='min', rsuffix='max')\n\n178 ms \xc2\xb1 6.29 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 50 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

比较前两个和最后一个,我们可以得出结论,DataFrameGroupBy.agg对于大型 DataFrame,使用速度要快一些。

\n

  • 我在任何情况下都不会期望我的答案是最快的(内部有两个分组的连接操作),但实际上对于新用户来说,对于 <100k 行,时间通常优先于可读性和适用性。只要不教坏习惯(比如当你可以拥有矢量化解决方案时使用 iterrows),我就会尝试以一种行之有效的方法为目标。 (2认同)
  • @CeliusStingher 谢谢你,我完全同意。在阅读 SO 帖子的多年中,我从未见过有人在简单的性能测试中提供这些详细信息。普通用户对它们不感兴趣。该设置是精确给出的,因此每个人(尤其是OP)都可以根据需要轻松比较自己机器上的计时。它不应被视为严格的基准,因为还需要进行更多测试。重点只是为了表明,对于足够大的数据,使用“agg”而不是“join”由于其实现而更快,这是我们都知道的。 (2认同)