将函数应用于 Pandas 行-行叉积

BBQ*_*cus 12 python dataframe pandas

我有两个 Pandas DataFrames/Series,每个包含一行。

df1 = pd.DataFrame([1, 2, 3, 4])
df2 = pd.DataFrame(['one', 'two', 'three', 'four'])
Run Code Online (Sandbox Code Playgroud)

我现在想将所有可能的组合放入一个 n*n 矩阵/DataFrame 中,所有交叉产品的值都是自定义函数的输出。

def my_function(x, y):
    return f"{x}:{y}"
Run Code Online (Sandbox Code Playgroud)

因此,这应该导致:

df = pd.DataFrame([['1:one', '2:one', '3:one', '4:one'],
                   ['1:two', '2:two', '3:two', '4:two'],
                   ['1:three', '2:three', '3:three', '4:three'],
                   ['1:four', '2:four', '3:four', '4:four']])

         0        1        2        3
0    1:one    2:one    3:one    4:one
1    1:two    2:two    3:two    4:two
2  1:three  2:three  3:three  4:three
3   1:four   2:four   3:four   4:four
Run Code Online (Sandbox Code Playgroud)

虽然我可以通过 构建我自己的矩阵itertools.product,但对于较大的数据集,这似乎是一种非常低效的方式,我想知道是否有更 Pythonic 的方式。先感谢您。

WeN*_*Ben 9

让我们试试 np.add.outer

df = pd.DataFrame(np.add.outer(df1[0].astype(str).values,':'+df2[0].values).T)
Out[258]: 
         0        1        2        3
0    1:one    2:one    3:one    4:one
1    1:two    2:two    3:two    4:two
2  1:three  2:three  3:three  4:three
3   1:four   2:four   3:four   4:four
Run Code Online (Sandbox Code Playgroud)


Sco*_*ton 8

您还可以使用 pd.DataFrame 构造函数apply

pd.DataFrame(index=df2.squeeze(), columns=df1.squeeze()).apply(lambda x: x.name.astype(str)+':'+x.index)
Run Code Online (Sandbox Code Playgroud)

输出:

            1        2        3        4                                        
one      1:one    2:one    3:one    4:one
two      1:two    2:two    3:two    4:two
three  1:three  2:three  3:three  4:three
four    1:four   2:four   3:four   4:four
Run Code Online (Sandbox Code Playgroud)

解释:

首先,使用 pd.DataFrame 构造函数,首先使用分别从 df2 和 df1 定义的索引和列构建和清空数据帧。使用pd.DataFrame.squeeze,我们将这些单列数据帧转换为 pd.Series。

接下来,使用pd.DataFrame.apply,我们可以应用一个 lambda 函数,该函数将列名中的字符串与一个冒号和数据帧每一列的数据帧索引相加。

这将生成一个带有索引和所需值的新数据框。


ank*_*_91 5

另一种使用方式np.tile

pd.DataFrame(np.tile(df1[0][:,None],df2.shape[0])).astype(str).add(":"+df2[0]).T
Run Code Online (Sandbox Code Playgroud)

或类似但没有调换礼貌@Ch3ster

pd.DataFrame(np.repeat(df1[0].astype(str)[None,:],df2.shape[0],axis=0)).add(':'+df2[0])
Run Code Online (Sandbox Code Playgroud)
         0        1        2        3
0    1:one    2:one    3:one    4:one
1    1:two    2:two    3:two    4:two
2  1:three  2:three  3:three  4:three
3   1:four   2:four   3:four   4:four
Run Code Online (Sandbox Code Playgroud)

编辑,

为了与您的功能一起使用,您还可以使用交叉连接:

def my_function(x, y):
    return f"{x}:{y}"

u = df1.assign(k=1).merge(df2.assign(k=1),on='k').drop('k',1).to_numpy()
arr = (np.array([*map(lambda x: my_function(*x),u)])
         .reshape((df1.shape[0],df2.shape[0]),order='F'))
Run Code Online (Sandbox Code Playgroud)
print(arr,"\n---------------------------------------------------\n",pd.DataFrame(arr))

[['1:one' '2:one' '3:one' '4:one']
 ['1:two' '2:two' '3:two' '4:two']
 ['1:three' '2:three' '3:three' '4:three']
 ['1:four' '2:four' '3:four' '4:four']] 
---------------------------------------------------
         0        1        2        3
0    1:one    2:one    3:one    4:one
1    1:two    2:two    3:two    4:two
2  1:three  2:three  3:three  4:three
3   1:four   2:four   3:four   4:four
Run Code Online (Sandbox Code Playgroud)