Подтвердить что ты не робот

Pandas Как фильтровать серию

У меня есть серия, подобная этой, после groupby ('name') и используемая функция mean() в другом столбце

name
383      3.000000
663      1.000000
726      1.000000
737      9.000000
833      8.166667

Может ли кто-нибудь показать мне, как отфильтровать строки со средними значениями 1.000000? Спасибо, и я очень благодарен вам за помощь.

4b9b3361

Ответ 1

In [5]:

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s = s[s != 1]
s
Out[0]:
383    3.000000
737    9.000000
833    8.166667
dtype: float64

Ответ 3

Быстрый способ сделать это - восстановить с помощью numpy, чтобы разрезать базовые массивы. См. Тайминги ниже.

mask = s.values != 1
pd.Series(s.values[mask], s.index[mask])

0
383    3.000000
737    9.000000
833    8.166667
dtype: float64

наивное время

введите описание изображения здесь

Ответ 4

Как DACW указал, есть улучшения цепочки методов в pandas 0.18.1, которые делают то, что вы ищете очень хорошо.

Вместо использования .where вы можете передать свою функцию либо индектеру .loc, либо индексу индекса [], и избегать вызова .dropna:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.loc[lambda x : x!=1]

test[lambda x: x!=1]

Аналогичное поведение поддерживается в классах DataFrame и NDFrame.

Ответ 5

Другой способ заключается в первую преобразовать в DataFrame и использовать query метод (предполагая, что вы numexpr установлен):

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s.to_frame(name='x').query("x != 1")

Ответ 6

Если вам нравится операция с цепочкой, вы также можете использовать функцию compress:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.compress(lambda x: x != 1)

# 383    3.000000
# 737    9.000000
# 833    8.166667
# dtype: float64

Ответ 7

В моем случае у меня была серия panda, где значения - это кортежи символов:

Out[67]
0    (H, H, H, H)
1    (H, H, H, T)
2    (H, H, T, H)
3    (H, H, T, T)
4    (H, T, H, H)

Поэтому я мог бы использовать индексирование для фильтрации серии, но для создания индекса мне понадобился apply. Мое условие "найти все кортежи, которые имеют ровно один" H ".

series_of_tuples[series_of_tuples.apply(lambda x: x.count('H')==1)]

Я признаю, что это не "цепной" (т.е. уведомление повторяю series_of_tuples дважды, вы должны хранить любые временные ряды в переменной, чтобы вы могли называть apply (...)).

Также могут быть и другие методы (кроме .apply(...)), которые могут работать элементарно для создания логического индекса.

Многие другие ответы (включая принятый ответ), используя связанные функции:

  • .compress()
  • .where()
  • .loc[]
  • []

Они принимают вызовы (lambdas) , которые применяются к Series, а не к отдельным значениям в этих сериях!

Поэтому моя серия кортежей вела себя странно, когда я пытался использовать мое выше условие /callable/lambda, с любой из цепочки функций, например .loc[]:

series_of_tuples.loc[lambda x: x.count('H')==1]

Выдает ошибку:

KeyError: "Уровень H должен быть таким же, как имя (нет)"

Я был очень смущен, но, похоже, использует Series.count series_of_tuples.count(...) function, чего я не хотел.

Я признаю, что альтернативная структура данных может быть лучше:

  • Тип данных категории?
  • Dataframe (каждый элемент кортежа становится столбцом)
  • Серия строк (просто объединяйте кортежи вместе):

Это создает последовательность строк (т.е. путем объединения кортежа, объединение символов в кортеж на одной строке)

series_of_tuples.apply(''.join)

Поэтому я могу использовать chainable Series.str.count

series_of_tuples.apply(''.join).str.count('H')==1