Я хотел бы фильтровать строки по функции каждой строки, например
def f(row):
return sin(row['velocity'])/np.prod(['masses']) > 5
df = pandas.DataFrame(...)
filtered = df[apply_to_all_rows(df, f)]
Или другой, более сложный, надуманный пример:
def g(row):
if row['col1'].method1() == 1:
val = row['col1'].method2() / row['col1'].method3(row['col3'], row['col4'])
else:
val = row['col2'].method5(row['col6'])
return np.sin(val)
df = pandas.DataFrame(...)
filtered = df[apply_to_all_rows(df, g)]
Как я могу это сделать?
apply
этой ситуации нет необходимости . Обычный логический индекс будет работать нормально.df[df['b] > df['c']]
. Есть очень мало ситуаций, которые действительно требуют,apply
и даже немногие, которые в этом нуждаются,axis=1
Предположим, у меня есть DataFrame следующим образом:
In [39]: df Out[39]: mass1 mass2 velocity 0 1.461711 -0.404452 0.722502 1 -2.169377 1.131037 0.232047 2 0.009450 -0.868753 0.598470 3 0.602463 0.299249 0.474564 4 -0.675339 -0.816702 0.799289
Я могу использовать sin и DataFrame.prod для создания логической маски:
In [40]: mask = (np.sin(df.velocity) / df.ix[:, 0:2].prod(axis=1)) > 0 In [41]: mask Out[41]: 0 False 1 False 2 False 3 True 4 True
Затем используйте маску для выбора из DataFrame:
In [42]: df[mask] Out[42]: mass1 mass2 velocity 3 0.602463 0.299249 0.474564 4 -0.675339 -0.816702 0.799289
источник
np.sin
автоматическая трансляция на все элементы. Что, если я заменю ее менее интеллектуальной функцией, которая может обрабатывать только один ввод за раз?Укажите также
reduce=True
для обработки пустых фреймов данных.import pandas as pd t = pd.DataFrame(columns=['a', 'b']) t[t.apply(lambda x: x['a'] > 1, axis=1, reduce=True)]
https://crosscompute.com/n/jAbsB6OIm6oCCJX9PBIbY5FECFKCClyV/-/apply-custom-filter-on-rows-of-dataframe
источник
Я не могу комментировать ответ Дакворда , но он не работает идеально. Он вылетает, когда фрейм данных пуст:
df = pandas.DataFrame(columns=['a', 'b', 'c']) df[df.apply(lambda x: x['b'] > x['c'], axis=1)]
Выходы:
ValueError: Must pass DataFrame with boolean values only
На мой взгляд, это похоже на ошибку в пандах, поскольку {} определенно является допустимым набором логических значений. Для решения обратитесь к ответу Роя Хёнджина Хана .
источник
Лучший подход, который я нашел, - вместо того,
reduce=True
чтобы избежать ошибок для пустого df (поскольку этот аргумент в любом случае устарел), просто проверьте, что размер df> 0 перед применением фильтра:def my_filter(row): if row.columnA == something: return True return False if len(df.index) > 0: df[df.apply(my_filter, axis=1)]
источник
Вы можете использовать
loc
свойство для фрагмента вашего фрейма данных.Согласно документации ,
loc
может бытьcallable function
аргумент as.In [3]: df = pandas.DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c']) In [4]: df Out[4]: a b c 0 -0.001968 -1.877945 -1.515674 1 -0.540628 0.793913 -0.983315 2 -1.313574 1.946410 0.826350 3 0.015763 -0.267860 -2.228350 4 0.563111 1.195459 0.343168 # define lambda function In [5]: myfilter = lambda x: x['b'] > x['c'] # use my lambda in loc In [6]: df1 = df.loc[fif]
если вы хотите объединить свою функцию фильтрации
fif
с другими критериями фильтрацииdf1 = df.loc[fif].loc[(df.b >= 0.5)]
источник