提问人:R_Student 提问时间:9/22/2023 最后编辑:user51R_Student 更新时间:9/22/2023 访问量:55
如何在 Pandas DataFrame 中选择分组变量中列的前 N 个键排序值
How to Select First N Key-ordered Values of column within a grouping variable in Pandas DataFrame
问:
我有一个数据集:
import pandas as pd
data = [
('A', 'X'),
('A', 'X'),
('A', 'Y'),
('A', 'Z'),
('B', 1),
('B', 1),
('B', 2),
('B', 2),
('B', 3),
('B', 3),
('C', 'L-7'),
('C', 'L-9'),
('C', 'L-9'),
('T', 2020),
('T', 2020),
('T', 2025)
]
df = pd.DataFrame(data, columns=['ID', 'SEQ'])
print(df)
我想创建一个密钥分组 ID 和 SEQ,以便选择每个 ID 组中每个不同 SEQ 的前 2 行
例如,ID A 有 3 个不同的键“A”、“X”、“A”、“Y”和“A Z”,按数据集的顺序排列,前两个键是“A X”和“A Y”,因此我必须选择每个键的前两行(如果可用),因此
“A X”、“A X”、“A Y”为什么?因为“A Z”是另一个键。
我尝试使用 groupby 和 head 函数,但我找不到实现此特定结果的方法。有人可以提供解决方案或为我指出正确的方向吗?
(df
.groupby(['ID','SEQ'])
.head(2)
)
但是正在重新运行原始数据集,我想知道你们是否可以帮助我使用方法转换来解决这个问题,因为这是我在 pandas 中的首选风格,提前非常感谢
最终正确的输出是
答:
drop_duplicates
然后用于获取每个“ID”。然后使用原始 DataFrame 来保留重复的行。groupby
head
merge
>>> df.drop_duplicates().groupby("ID").head(2).merge(df)
ID SEQ
0 A X
1 A X
2 A Y
3 B 1
4 B 1
5 B 2
6 B 2
7 C L-7
8 C L-9
9 C L-9
10 T 2020
11 T 2020
12 T 2025
IIUC,您必须仅按 ID 分组,然后仅选择唯一行(例如,通过使用 ),然后您可以使用来检索这些行:drop_duplicates
merge
df = df.\
merge(
df.\
drop_duplicates().\
groupby(["ID"]).\
head(2),
on=["ID", "SEQ"],
how="right"
)
df
Out[16]:
ID SEQ
0 A X
1 A X
2 A Y
3 B 1
4 B 1
5 B 2
6 B 2
7 C L-7
8 C L-9
9 C L-9
10 T 2020
11 T 2020
12 T 2025
您先使用 groupby,然后使用 head(2) 的方法是正确的,可以获取每个 ID 组中每个不同 SEQ 的前 2 行。
但是,额外的要求是每个 ID 中仅获取前 2 个唯一的 SEQ 组。为此,您可以:
创建一个新列,该列在每个 ID 组中具有唯一 SEQ 的排名。 使用此排名筛选出数据。 最后,使用原始方法获取每个 ID 组中每个 SEQ 的前 2 行。 下面是使用方法链接的解决方案:
result = (df
.assign(rank=df.groupby('ID')['SEQ'].transform(lambda x: x.rank(method='dense')))
.query('rank <= 2')
.groupby(['ID', 'SEQ'])
.head(2)
.drop(columns=['rank'])
)
print(result)
这应该为您提供所需的输出。
评论
这是使用pd.factorize()
groupby()
df.loc[df.groupby('ID')['SEQ'].transform(lambda x: pd.factorize(x)[0] <= 1)]
输出:
ID SEQ
0 A X
1 A X
2 A Y
4 B 1
5 B 1
6 B 2
7 B 2
10 C L-7
11 C L-9
12 C L-9
13 T 2020
14 T 2020
15 T 2025
评论
df[df.groupby('ID')['SEQ'].transform(lambda g: g.rank(method='dense')<=2)]
.rank()
尝试:
out = df.groupby("ID", group_keys=False).apply(
lambda x: x[x["SEQ"].isin(x["SEQ"].unique()[:2])]
)
print(out)
指纹:
ID SEQ
0 A X
1 A X
2 A Y
4 B 1
5 B 1
6 B 2
7 B 2
10 C L-7
11 C L-9
12 C L-9
13 T 2020
14 T 2020
15 T 2025
评论
.apply
.apply
.apply
.apply
评论