Nice programing

pandas : DataFrame 행에 대한 복잡한 필터

nicepro 2020. 10. 14. 20:56
반응형

pandas : DataFrame 행에 대한 복잡한 필터


각 행의 함수로 행을 필터링하고 싶습니다. 예 :

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)]

어떻게 할 수 있습니까?


DataFrame.apply주어진 축을 따라 함수를 적용하는를 사용하여이 작업을 수행 할 수 있습니다 .

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

In [6]: df[df.apply(lambda x: x['b'] > x['c'], axis=1)]
Out[6]: 
          a         b         c
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

다음과 같이 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

reduce=True빈 DataFrame도 처리하도록 지정하십시오 .

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


나는 duckworthd의 대답 에 대해 언급 할 수 없지만 완벽하게 작동하지 않습니다. 데이터 프레임이 비어 있으면 충돌합니다.

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

{}은 확실히 유효한 부울 값 집합이기 때문에 나에게 판다의 버그처럼 보입니다.


The best approach I've found is, instead of using reduce=True to avoid errors for empty df (since this arg is deprecated anyway), just check that df size > 0 before applying the filter:

def my_filter(row):
    if row.columnA == something:
        return True

    return False

if len(df.index) > 0:
    df[df.apply(my_filter, axis=1)]

참고URL : https://stackoverflow.com/questions/11418192/pandas-complex-filter-on-rows-of-dataframe

반응형