优化 Pandas Dataframe 的 min-max 和 groupby 查询
Optimize min-max and groupby query for Pandas Dataframe
我有一个如下所示的输入数据框:
col0 col1 name
0 g0 100 n1
1 g0 120 n1
2 g1 40 n3
3 g1 30 n4
4 g2 10 n5
5 g2 100 n5
6 g2 250 n5
我想获得一个新的数据帧(或相同,没关系),其中 col1
和 col2
分别包含每个元组的最小值和最大值 (col0, name)
.我可以使用以下代码片段执行此操作:
import pandas as pd
data = {'col0': ["g0", "g0", "g1", "g1", "g2", "g2", "g2"], 'col1': [100, 120, 40, 30, 10, 100, 250], 'name': ["n1", "n1", "n3", "n4", "n5", "n5", "n5"]}
df = pd.DataFrame(data=data)
df_res = pd.DataFrame()
names = df["name"].unique()
for name in names:
literals = df[df["name"] == name]["col0"].unique()
for literal in literals:
min_val = df[(df["name"] == name) &
(df["col0"] == literal)]["col1"].min()
max_val = df[(df["name"] == name) &
(df["col0"] == literal)]["col1"].min()
elem = {"col0": literal, "col1": min_val, "col2": max_val,
"name": name}
df_res = df_res.append(elem, ignore_index=True)
它给出了存储在df_res
上的所需输出,如下所示:
col0 col1 col2 name
0 g0 100.0 100.0 n1
1 g1 40.0 40.0 n3
2 g1 30.0 30.0 n4
3 g2 10.0 10.0 n5
问题是我必须使用具有 95K 寄存器的数据帧进行此转换,而且我的方法非常慢(需要几分钟才能完成)。
因此,我的问题是:有没有办法优化这个操作?
您可以使用 groupby.agg
并传递 min
和 max
以获得所需的列。要将自定义名称设置为聚合列,您可以使用命名聚合,将最小列命名为 col1
并将最大列命名为 col2
:
out = df.groupby(['col0','name'], as_index=False).agg(col1=('col1','min'), col2=('col1','max'))
同样的代码换一种方式:
out = df.groupby(['col0','name'])['col1'].agg(['min','max']).set_axis(['col1','col2'], axis=1).reset_index()
输出:
col0 name col1 col2
0 g0 n1 100 120
1 g1 n3 40 40
2 g1 n4 30 30
3 g2 n5 10 250
我有一个如下所示的输入数据框:
col0 col1 name
0 g0 100 n1
1 g0 120 n1
2 g1 40 n3
3 g1 30 n4
4 g2 10 n5
5 g2 100 n5
6 g2 250 n5
我想获得一个新的数据帧(或相同,没关系),其中 col1
和 col2
分别包含每个元组的最小值和最大值 (col0, name)
.我可以使用以下代码片段执行此操作:
import pandas as pd
data = {'col0': ["g0", "g0", "g1", "g1", "g2", "g2", "g2"], 'col1': [100, 120, 40, 30, 10, 100, 250], 'name': ["n1", "n1", "n3", "n4", "n5", "n5", "n5"]}
df = pd.DataFrame(data=data)
df_res = pd.DataFrame()
names = df["name"].unique()
for name in names:
literals = df[df["name"] == name]["col0"].unique()
for literal in literals:
min_val = df[(df["name"] == name) &
(df["col0"] == literal)]["col1"].min()
max_val = df[(df["name"] == name) &
(df["col0"] == literal)]["col1"].min()
elem = {"col0": literal, "col1": min_val, "col2": max_val,
"name": name}
df_res = df_res.append(elem, ignore_index=True)
它给出了存储在df_res
上的所需输出,如下所示:
col0 col1 col2 name
0 g0 100.0 100.0 n1
1 g1 40.0 40.0 n3
2 g1 30.0 30.0 n4
3 g2 10.0 10.0 n5
问题是我必须使用具有 95K 寄存器的数据帧进行此转换,而且我的方法非常慢(需要几分钟才能完成)。
因此,我的问题是:有没有办法优化这个操作?
您可以使用 groupby.agg
并传递 min
和 max
以获得所需的列。要将自定义名称设置为聚合列,您可以使用命名聚合,将最小列命名为 col1
并将最大列命名为 col2
:
out = df.groupby(['col0','name'], as_index=False).agg(col1=('col1','min'), col2=('col1','max'))
同样的代码换一种方式:
out = df.groupby(['col0','name'])['col1'].agg(['min','max']).set_axis(['col1','col2'], axis=1).reset_index()
输出:
col0 name col1 col2
0 g0 n1 100 120
1 g1 n3 40 40
2 g1 n4 30 30
3 g2 n5 10 250