简体   繁体   中英

pandas apply function that returns a DataFrame

Say I have a DataFrame (or Series) of arguments , and a function f which takes those arguments and returns a DataFrame.

eg

arguments = pd.DataFrame({"a": [2, 3], "b": [10, 100]})

df = pd.DataFrame({"x": [1, 0, 0], "y": [0, 1, 0], "z": [0, 0, 1]})
def f(a, b):
    return df*a*b

I want to get a DataFrame that stacks the DataFrames obtained from applying f to the arguments in each row of arguments :

     x    y    z
0   20    0    0
1    0   20    0
2    0    0   20
0  300    0    0
1    0  300    0
2    0    0  300

I can achieve this by explicitly constructing the result as follows...

pd.concat(f(a=row["a"], b=row["b"]) for _, row in arguments.iterrows())

...but as this is basically just an apply for a function that returns DataFrames, I was wondering if there's a pandas method for doing it.

Maybe you can convert the DataFrames to numpy arrays and use elementwise multiplication:

multiplier = np.kron(arguments['a'].mul(arguments['b']).to_numpy(), np.ones(([*df.shape]), dtype=int)).T
pd.DataFrame(np.tile(df.to_numpy(), (len(arguments), 1)) * multiplier, columns=df.columns)

Output:

     x    y    z
0   20    0    0
1    0   20    0
2    0    0   20
3  300    0    0
4    0  300    0
5    0    0  300

I think your solution is good. It's also very readable, which is important. The only thing I'd change is the way you're looping over the dataframe and passing the arguments.

Instead of user iterrows , you can use to_dict('series') , which will return a list of dicts that can be nicely expanding as keyword arguments to f :

df = pd.concat(f(**args) for args in arguments.to_dict('records'))

Output:

>>> df
     x    y    z
0   20    0    0
1    0   20    0
2    0    0   20
0  300    0    0
1    0  300    0
2    0    0  300

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM