Ответ 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
У меня есть серия, подобная этой, после groupby ('name') и используемая функция mean() в другом столбце
name
383 3.000000
663 1.000000
726 1.000000
737 9.000000
833 8.166667
Может ли кто-нибудь показать мне, как отфильтровать строки со средними значениями 1.000000? Спасибо, и я очень благодарен вам за помощь.
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
Из pandas версии 0.18+ фильтрация серии также может быть выполнена ниже
test = {
383: 3.000000,
663: 1.000000,
726: 1.000000,
737: 9.000000,
833: 8.166667
}
pd.Series(test).where(lambda x : x!=1).dropna()
заказ: http://pandas.pydata.org/pandas-docs/version/0.18.1/whatsnew.html#method-chaininng-improvements
Быстрый способ сделать это - восстановить с помощью 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
наивное время
Как 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.
Другой способ заключается в первую преобразовать в 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")
Если вам нравится операция с цепочкой, вы также можете использовать функцию 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
В моем случае у меня была серия 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, чего я не хотел.
Я признаю, что альтернативная структура данных может быть лучше:
Это создает последовательность строк (т.е. путем объединения кортежа, объединение символов в кортеж на одной строке)
series_of_tuples.apply(''.join)
Поэтому я могу использовать chainable Series.str.count
series_of_tuples.apply(''.join).str.count('H')==1