Скажем, у меня есть фрейм данных, и я хочу подсчитать, сколько раз у нас есть элемент, например, [1,5,2] в каждом столбце.

Я мог бы сделать что-то вроде

elem_list = [1,5,2]

for e in elemt_list:
 (df["col1"]==e).sum()

Но нет ли лучшего способа, как

elem_list = [1,5,2]
df["col1"].count_elements(elem_list)

#1 5    # 1 occurs 5 times
#5 3    # 5 occurs 3 times
#2 0    # 2 occurs 0 times

Обратите внимание, что он должен подсчитывать все элементы в списке и возвращать «0», если элемент в списке не находится в столбце.

2
CutePoison 18 Янв 2022 в 17:16
К вашему сведению, то, что я изначально предложил, является самым быстрым, сначала value_counts, затем reindex. Другие методы имеют стоимость фильтрации или построения категориального.
 – 
mozway
18 Янв 2022 в 17:39

4 ответа

Лучший ответ

Перейдите к Categorical, который вернет 0 для отсутствующего элемента

pd.Categorical(df['col1'],elem_list).value_counts()
Out[62]: 
1    3
5    0
2    1
dtype: int64
2
BENY 18 Янв 2022 в 17:25

Вы могли бы сделать что-то вроде этого:

df = pd.DataFrame({"col1":np.random.randint(0,10, 100)})
df[df["col1"].isin([0,1])].value_counts()

# col1
# 1       17
# 0       10
# dtype: int64
1
Ssayan 18 Янв 2022 в 17:23

Первый фильтр по Series.isinи DataFrame.loc, а затем используйте Series.value_counts, последним, если важен порядок, добавьте Series.reindex:

df.loc[df["col1"].isin(elem_list), 'col1'].value_counts().reindex(elem_list, fill_values=0)
1
jezrael 18 Янв 2022 в 17:24
Будет ли это также учитывать элементы, которых нет в фрейме даты? (т.е. пропущенное значение)
 – 
sagi
18 Янв 2022 в 17:22
- нет, считает только отфильтрованные значения из списка
 – 
jezrael
18 Янв 2022 в 17:23
2
OP также хотел, чтобы эти значения присутствовали со счетом 0..
 – 
sagi
18 Янв 2022 в 17:23

Вы можете использовать value_counts и < a href="http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.reindex.html" rel="nofollow noreferrer">reindex:

df = pd.DataFrame({'col1': [1,1,5,1,5,1,1,4,3]})

elem_list = [1,5,2]
df['col1'].value_counts().reindex(elem_list, fill_value=0)

Выход:

1    5
5    2
2    0

Эталон (100 000 значений):

# setup
df = pd.DataFrame({'col1': np.random.randint(0,10, size=100000)})

df['col1'].value_counts().reindex(elem_list, fill_value=0)
# 774 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

pd.Categorical(df['col1'],elem_list).value_counts()
# 2.72 ms ± 125 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

df.loc[df["col1"].isin(elem_list), 'col1'].value_counts().reindex(elem_list, fill_value=0)
# 2.98 ms ± 152 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1
mozway 18 Янв 2022 в 17:38
df = pd.DataFrame({'col1': np.random.randint(0,1000, size=100000)}) ?
 – 
jezrael
18 Янв 2022 в 17:40
1
Более или менее одинаковые значения в том же порядке, от 900 мкс до 2 мс. Я предполагаю, что все решения должны прочитать все элементы хотя бы один раз. В моем случае это делается непосредственно для подсчета, затем делается.
 – 
mozway
18 Янв 2022 в 17:44