将功能应用于熊猫行行交叉产品

时间:2020-08-03 14:45:35

标签: python pandas dataframe

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

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

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

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

因此,这将导致:

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

虽然我可以通过itertools.product构建自己的矩阵,但对于大型数据集而言,这似乎是一种非常低效的方法,我想知道是否还有一种更Python化的方法。预先谢谢你。

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:8)

您还可以将pd.DataFrame构造函数与apply一起使用:

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

输出:

            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

说明:

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

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

这将创建一个具有索引和所需值的新数据框。

答案 2 :(得分:5)

使用np.tile的另一种方法:

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

或类似但不转载@ Ch3ster礼貌

pd.DataFrame(np.repeat(df1[0].astype(str)[None,:],df2.shape[0],axis=0)).add(':'+df2[0])

         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

编辑

要与函数一起使用,还可以使用交叉联接:

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

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

答案 3 :(得分:4)

您可以添加它们,但是使用numpy.ndarray.ravel

展平第一个df
pd.DataFrame(df1.astype(str).to_numpy().ravel() + ':' + df2.to_numpy())

         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

答案 4 :(得分:2)

仅出于完整性考虑,以上答案仅适用于简单的用例。对于更复杂的自定义函数,这可能是最简单的(尽管有点难看)选项:

df = []
for i in df1.iterrows():
    row = [] 
    for j in df2.iterrows():
        row.append(my_function(i[1][0], j[1][0]))
    df.append(row)

pd.DataFrame(df)