определить функцию, используя другие имена функций в качестве параметра - PullRequest
0 голосов
/ 06 октября 2018

У меня есть DataFrame, как показано ниже:

df = {'col_1': [1,2,3,4,5,6,7,8,9,10],
      'col_2': [1,2,3,4,5,6,7,8,9,10],
      'col_3':['A','A','A','A','A','B','B','B','B','B']}
df = pd.DataFrame(df)

, в то время как реальные данные, которые я использую, содержат сотни столбцов, я хочу манипулировать этими столбцами, используя различные функции, такие как min, maxа также самоопределяемая функция, такая как:

def dist(x):
    return max(x) - min(x)
def HHI(x):
    ss = sum([s**2 for s in x])
    return ss

Вместо того, чтобы записывать много строк, я хочу иметь такую ​​функцию:

def myfunc(cols,fun):
    return df.groupby('col_3')[[cols]].transform(lambda x: fun)
# which allow me to do something like:

df[['min_' + s for s in cols]] = myfunc(cols, min)
df[['max_' + s for s in cols]] = myfunc(cols, max)
df[['dist_' + s for s in cols]] = myfunc(cols, dist)

Возможно ли это в Python (мое предположение "да")?
Тогда как, если да?

РЕДАКТИРОВАТЬ ====== О НАЗВАНИИ САМОПРЕДЕЛЕННОЙ ФУНКЦИИ =======
В соответствии с решением jpp, то, о чем я просил, возможно, по крайней мере для встроенных функций, требуется больше работы в отношении самоопределяемой функции.

Работоспособное решение,

temp = df.copy()
for func in ['HHI','DIST'] :
    print(func)
    temp[[ func + s for s in cols]] = df.pipe(myfunc,cols,eval(func))

Ключевым моментом здесь является использование eval перестройки для преобразования строкового выражения как функции.Тем не менее, может быть лучший способ сделать это, с нетерпением жду, чтобы увидеть.

РЕДАКТИРОВАТЬ ====== за комментарий jpp о названии самоопределяемой функции =======

Комментарий jpp, который передает имя функции непосредственно в myfun, действителен на основании моего теста, однако новое имя столбца на основе func будет выглядеть примерно так: <function HHI at 0x00000194460019D8>, что не оченьчитаемая, модификация temp[[ str(func.__name__) + s for s in cols]], надеюсь, это поможет тем, кто придет к этой проблеме позже.

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Да, вы очень близки:

def myfunc(cols,fun):
    return df.groupby('col_3')[cols].transform(lambda x: fun(x))

Или:

def myfunc(cols,fun):
    return df.groupby('col_3')[cols].transform(fun)
0 голосов
/ 06 октября 2018

Вот один из способов использования pd.DataFrame.pipe.

С Python все является объектом и может быть передано без проверки типов.Философия такова: «Не проверяйте, работает ли это, просто попробуйте ...».Следовательно, вы можете передать строку или функцию в myfunc, а затем в transform без каких-либо вредных побочных эффектов.

def myfunc(df, cols, fun):
    return df.groupby('col_3')[cols].transform(fun)

cols = ['col_1', 'col_2']

df[[f'min_{s}' for s in cols]] = df.pipe(myfunc, cols, 'min')
df[[f'max_{s}' for s in cols]] = df.pipe(myfunc, cols, 'max')
df[[f'dist_{s}' s in cols]] = df.pipe(myfunc, cols, lambda x: x.max() - x.min())

Результат:

print(df)

   col_1  col_2 col_3  min_col_1  min_col_2  max_col_1  max_col_2  dist_col_1  \
0      1      1     A          1          1          5          5           4   
1      2      2     A          1          1          5          5           4   
2      3      3     A          1          1          5          5           4   
3      4      4     A          1          1          5          5           4   
4      5      5     A          1          1          5          5           4   
5      6      6     B          6          6         10         10           4   
6      7      7     B          6          6         10         10           4   
7      8      8     B          6          6         10         10           4   
8      9      9     B          6          6         10         10           4   
9     10     10     B          6          6         10         10           4   

   dist_col_2  
0           4  
1           4  
2           4  
3           4  
4           4  
5           4  
6           4  
7           4  
8           4  
9           4  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...