pandas 数据框中具有选择条件的有效最大选择
Efficient max selection in pandas dataframe with selection condition
我有一个 pandas 数据框,其中包含列(除其他外)user_id
和 start_time
。我想高效且可读地找到与每个用户的最大值相关联的所有行 start_time
.
例如,如果这是我的数据:
user_id start_time A B C
1 37 a b c
1 45 d e f
1 45 g h i
2 58 j k l
2 17 m n o
2 58 p q r
3 2 s t u
那么我希望找到
user_id start_time A B C
1 45 d e f
1 45 g h i
2 58 j k l
2 58 p q r
3 2 s t u
我一直在想出有点像 的解决方案,但它找到了最新的 start time
的 user_id
,而不是 table 的选择每个用户最多 start_time
。
当然,如果我手动迭代DataFrame很容易,但是效率很低。
感谢您的指点。
为了方便未来的读者,生成数据帧如下:
columns = ['user_id', 'start_time', 'A', 'B', 'C']
LoL = [
[1, 37, 'a', 'b', 'c'],
[1, 45, 'd', 'e', 'f'],
[1, 45, 'g', 'h', 'i'],
[2, 58, 'j', 'k', 'l'],
[2, 17, 'm', 'n', 'o'],
[2, 58, 'p', 'q', 'r'],
[3, 2, 's', 't', 'u']]
pd.DataFrame = (LoL, columns=columns)
您可以对 user_id 列进行分组,然后调用 apply
并传递一个 lambda 来过滤开始时间等于最大值的结果,我们希望从中生成一个布尔索引这个。然后我们可以调用 reset_index
但由于 groupby 被过滤的方式,我们将收到重复列的错误,因此我们必须删除此重复列:
In [66]:
gp = df.groupby('user_id')
gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()]).reset_index(drop=True)
Out[66]:
user_id start_time A B C
0 1 45 d e f
1 1 45 g g i
2 2 58 j k l
3 2 58 p q r
4 3 2 s t u
如果我们没有调用 reset_index
你会得到重复的值:
In [67]:
gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()])
Out[67]:
user_id start_time A B C
user_id
1 1 1 45 d e f
2 1 45 g g i
2 3 2 58 j k l
5 2 58 p q r
3 6 3 2 s t u
内部布尔条件在多索引上生成布尔掩码,然后需要将其传递给 lambda 以生成上述内容:
In [68]:
gp.apply(lambda x: x['start_time'] == x['start_time'].max())
Out[68]:
user_id
1 0 False
1 True
2 True
2 3 True
4 False
5 True
3 6 True
Name: start_time, dtype: bool
或者您可以这样做:
df[df.start_time == df.groupby('user_id')['start_time'].transform(max)]
产生:
user_id start_time A B C
1 1 45 d e f
2 1 45 g h i
3 2 58 j k l
5 2 58 p q r
6 3 2 s t u
我有一个 pandas 数据框,其中包含列(除其他外)user_id
和 start_time
。我想高效且可读地找到与每个用户的最大值相关联的所有行 start_time
.
例如,如果这是我的数据:
user_id start_time A B C
1 37 a b c
1 45 d e f
1 45 g h i
2 58 j k l
2 17 m n o
2 58 p q r
3 2 s t u
那么我希望找到
user_id start_time A B C
1 45 d e f
1 45 g h i
2 58 j k l
2 58 p q r
3 2 s t u
我一直在想出有点像 start time
的 user_id
,而不是 table 的选择每个用户最多 start_time
。
当然,如果我手动迭代DataFrame很容易,但是效率很低。
感谢您的指点。
为了方便未来的读者,生成数据帧如下:
columns = ['user_id', 'start_time', 'A', 'B', 'C']
LoL = [
[1, 37, 'a', 'b', 'c'],
[1, 45, 'd', 'e', 'f'],
[1, 45, 'g', 'h', 'i'],
[2, 58, 'j', 'k', 'l'],
[2, 17, 'm', 'n', 'o'],
[2, 58, 'p', 'q', 'r'],
[3, 2, 's', 't', 'u']]
pd.DataFrame = (LoL, columns=columns)
您可以对 user_id 列进行分组,然后调用 apply
并传递一个 lambda 来过滤开始时间等于最大值的结果,我们希望从中生成一个布尔索引这个。然后我们可以调用 reset_index
但由于 groupby 被过滤的方式,我们将收到重复列的错误,因此我们必须删除此重复列:
In [66]:
gp = df.groupby('user_id')
gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()]).reset_index(drop=True)
Out[66]:
user_id start_time A B C
0 1 45 d e f
1 1 45 g g i
2 2 58 j k l
3 2 58 p q r
4 3 2 s t u
如果我们没有调用 reset_index
你会得到重复的值:
In [67]:
gp.apply(lambda x: x[x['start_time'] == x['start_time'].max()])
Out[67]:
user_id start_time A B C
user_id
1 1 1 45 d e f
2 1 45 g g i
2 3 2 58 j k l
5 2 58 p q r
3 6 3 2 s t u
内部布尔条件在多索引上生成布尔掩码,然后需要将其传递给 lambda 以生成上述内容:
In [68]:
gp.apply(lambda x: x['start_time'] == x['start_time'].max())
Out[68]:
user_id
1 0 False
1 True
2 True
2 3 True
4 False
5 True
3 6 True
Name: start_time, dtype: bool
或者您可以这样做:
df[df.start_time == df.groupby('user_id')['start_time'].transform(max)]
产生:
user_id start_time A B C
1 1 45 d e f
2 1 45 g h i
3 2 58 j k l
5 2 58 p q r
6 3 2 s t u