USe groupby
+ transform
для широковещательной передачи размера «ID» каждой строке этого идентификатора, затем вы можете создать логическую маску для среза, используя between
import pandas as pd
df = pd.DataFrame({'ID': ['A']*6 +['B']*15 +['C']*5})
df[df.groupby('ID')['ID'].transform('size').between(5, 15, inclusive=False)]
ID
0 A
1 A
2 A
3 A
4 A
5 A
С точки зрения производительности между использованием groupby
+ transform
или нарезкой индекса с помощью value_counts
особой разницы нет. (На самом деле методы value_counts кажутся немного быстрее, если вы думаете, что планируете фильтровать большинство групп (скажем, большинство из них имеют размер 1-2) или если вы планируете оставить большинство групп (большинство из них имеют размер >> 15))
import perfplot
import pandas as pd
import numpy as np
def transform(df):
return df[df.groupby('ID')['ID'].transform('size').between(5, 15, inclusive=False)]
def value_counts_slice(df):
counts = df['ID'].value_counts()
return df[df['ID'].isin(counts.index[(counts > 5) & (counts < 15)])]
perfplot.show(
setup=lambda n: pd.DataFrame({'ID': np.random.randint(0, n, 15*n)}),
kernels=[
lambda df: transform(df),
lambda df: value_counts_slice(df),
],
labels=["Transform", "Value Counts"],
n_range=[2 ** k for k in range(2,21)],
equality_check=np.allclose,
xlabel="Number of ID Groups"
)
введите описание изображения здесь