Эффективный эквивалент Python-панд / реализация R sweep с несколькими аргументами - PullRequest
0 голосов
/ 11 февраля 2019

Другие вопросы, пытающиеся предоставить функцию python, эквивалентную R * sweep (например, здесь ), на самом деле не касаются случая множественных аргументов, где это наиболее полезно.

Скажем, я хочу применить функцию 2 аргументов к каждой строке Dataframe с соответствующим элементом из столбца другого DataFrame:

df = data.frame("A" = 1:3,"B" = 11:13)
df2= data.frame("X" = 10:12,"Y" = 10000:10002)
sweep(df,1, FUN="*",df2$X)

В python Я получил эквивалент, используяapply на то, что в основном представляет собой цикл по ряду строк.

df = pd.DataFrame( { "A" : range(1,4),"B" : range(11,14) } )
df2 = pd.DataFrame( { "X" : range(10,13),"Y" : range(10000,10003) } )
pd.Series(range(df.shape[0])).apply(lambda row_count: np.multiply(df.iloc[row_count,:],df2.iloc[row_count,df2.columns.get_loc('X')]))

Я очень сомневаюсь, что это эффективно в pandas, как лучше это сделать?

При применении *:

   A   B
1 10 110
2 22 132
3 36 156

оба бита кода должны приводить к кадру данных / матрице из 6 чисел. Я должен четко заявить, что цель состоит в том, чтобы вставить в него свою собственную функциюsweep подобное поведение говорит:

df = data.frame("A" = 1:3,"B" = 11:13)
df2= data.frame("X" = 10:12,"Y" = 10000:10002)
myFunc = function(a,b) { floor((a + b)^min(a/2,b/3))  }
sweep(df,1, FUN=myFunc,df2$X)

, что приводит к:

 A B
[1,] 3 4
[2,] 3 4
[3,] 3 5

Каков хороший способ сделать это в пандах Python?

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Если я правильно понимаю, вы пытаетесь применить двоичную функцию f (x, y) к кадру данных (для x) построчно с аргументами из ряда для y.Один из способов сделать это - позаимствовать реализацию у самой внутренней части панды.Если вы хотите расширить эту функцию (например, применить к столбцам, это можно сделать аналогичным образом, если f является двоичным. Если вам нужно больше аргументов, вы можете просто сделать partial для f, чтобы сделать его двоичным

import pandas as pd
from pandas.core.dtypes.generic import ABCSeries

def sweep(df, series, FUN):
    assert isinstance(series, ABCSeries)

    # row-wise application
    assert len(df) == len(series)
    return df._combine_match_index(series, FUN)


# define your binary operator
def f(x, y):
    return x*y    

# the input data frames
df = pd.DataFrame( { "A" : range(1,4),"B" : range(11,14) } )
df2 = pd.DataFrame( { "X" : range(10,13),"Y" : range(10000,10003) } )

# apply
test1 = sweep(df, df2.X, f)

# performance
# %timeit sweep(df, df2.X, f)
# 155 µs ± 1.27 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)#

# another method
import numpy as np
test2 = pd.Series(range(df.shape[0])).apply(lambda row_count: np.multiply(df.iloc[row_count,:],df2.iloc[row_count,df2.columns.get_loc('X')]))

# %timeit performance
# 1.54 ms ± 56.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

assert all(test1 == test2)

Надеюсь, это поможет.

0 голосов
/ 11 февраля 2019

В pandas

df.mul(df2.X,axis=0)
    A    B
0  10  110
1  22  132
2  36  156
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...