В моем реальном случае у меня есть набор временных рядов, связанных с разными идентификаторами, хранящимися в одном DataFrame
Некоторые состоят из 400 семплов, некоторые из 1000 семплов, некоторые из 2000. Они хранятся в одном df и:
Я хотел бы отбросить все идентификаторы, состоящие из временных рядов короче заданной длины.
Я написал следующий код, но считаю его очень некрасивым и неэффективным.
import pandas as pd
import numpy as np
dict={"samples":[1,2,3,4,5,6,7,8,9],"id":["a","b","c","b","b","b","c","c","c"]}
df=pd.DataFrame(dict)
df_id=pd.DataFrame()
for i in set(df.id):
df_filtered=df[df.id==i]
len_id=len(df_filtered.samples)
if len_id>3: #3 is just a random choice for this example
df_id=df_id.append(df_filtered)
print(df_id)
Выход:
samples id
2 3 c
6 7 c
7 8 c
8 9 c
1 2 b
3 4 b
4 5 b
5 6 b
Как улучшить его более питоническим способом? Спасибо
2 ответа
Хороший ответ Юхо. Другой вариант — это groupby-filter
:
df.groupby('id').filter(lambda group: len(group) > 3)
# samples id
# 1 2 b
# 2 3 c
# 3 4 b
# 4 5 b
# 5 6 b
# 6 7 c
# 7 8 c
# 8 9 c
Чтобы точно соответствовать вашему порядку вывода, добавьте убывающий id
Сортировать: .sort_values('id', ascending=False)
Есть много решений. Например, вы можете использовать групповое преобразование и отбрасывать «маленькие» образцы. Подходящее решение будет зависеть от ваших требований, т. Е. Проведете ли вы предварительную обработку один раз, а затем сбросите разные образцы?
Во всяком случае, учтите:
import pandas as pd
df = pd.DataFrame({"samples": [1,2,3,4,5,6,7,8,9], "id": ["a","b","c","b","b","b","c","c","c"]})
df["counts"] = df.groupby("id")["samples"].transform("count")
df[df["counts"] > 3]
# Or if you want:
df[df["counts"] > 3].drop(columns="counts")
Кстати, избегайте использования dict
как имя переменной.
Это тоже здорово.
— Юхо