2

我有两个熊猫数据框,如下所示:

import pandas as pd

df_one = pd.DataFrame( {
    'A': [1,1,2,3,4,4,4],
    'B1': [0.5,0.0,0.2,0.1,0.3,0.2,0.1],
    'B2': [0.2,0.3,0.1,0.5,0.3,0.1,0.2],
    'B3': [0.1,0.2,0.0,0.9,0.0,0.3,0.5]} );
df_two = pd.DataFrame( {
    'A': [1,2,3,4],
    'C1': [1.0,9.0,2.1,9.0],
    'C2': [2.0,3.0,0.7,1.1],
    'C3': [5.0,4.0,2.3,3.4]} );

df_one
   A   B1   B2   B3
0  1  0.5  0.2  0.1
1  1  0.0  0.3  0.2
2  2  0.2  0.1  0.0
3  3  0.1  0.5  0.9
4  4  0.3  0.3  0.0
5  4  0.2  0.1  0.3
6  4  0.1  0.2  0.5

df_two
   A   C1   C2   C3
0  1  1.0  2.0  5.0
1  2  9.0  3.0  4.0
2  3  2.1  0.7  2.3
3  4  9.0  1.1  3.4

我想做的是计算一个标量积,其中我将第一个数据帧的行乘以第二个数据帧的行,\sum_i B_i * C_i即仅当A列的值在两个帧中都匹配时,才通过第二个数据帧中的一行。我知道如何循环和使用 if,但我想以更有效的类似 numpy 或类似 pandas 的方式来做到这一点。非常感谢任何帮助:)

4

3 回答 3

1

另一种方法与此类似:

import pandas as pd

df_one = pd.DataFrame( {
    'A': [1,1,2,3,4,4,4],
    'B1': [0.5,0.0,0.2,0.1,0.3,0.2,0.1],
    'B2': [0.2,0.3,0.1,0.5,0.3,0.1,0.2],
    'B3': [0.1,0.2,0.0,0.9,0.0,0.3,0.5]} );
df_two = pd.DataFrame( {
    'A': [1,2,3,4],
    'C1': [1.0,9.0,2.1,9.0],
    'C2': [2.0,3.0,0.7,1.1],
    'C3': [5.0,4.0,2.3,3.4]} );
lookup = df_two.groupby(df_two.A)

def multiply_rows(row):
    other = lookup.get_group(row['A'])
    # We want every column after "A"
    x = row.values[1:]
    # In this case, other is a 2D array with one row, similar to "row" above...
    y = other.values[0, 1:]
    return x.dot(y)

# The "axis=1" makes each row to be passed in, rather than each column
result = df_one.apply(multiply_rows, axis=1)
print result

这导致:

0    1.40
1    1.60
2    2.10
3    2.63
4    3.03
5    2.93
6    2.82
于 2013-07-15T21:49:49.223 回答
1

不确定是否需要 A 列的唯一值(如果需要,请在下面的结果中使用 groupby)

pd.merge(df_one, df_two, on='A')
   A   B1   B2   B3   C1   C2   C3
0  1  0.5  0.2  0.1  1.0  2.0  5.0
1  1  0.0  0.3  0.2  1.0  2.0  5.0
2  2  0.2  0.1  0.0  9.0  3.0  4.0
3  3  0.1  0.5  0.9  2.1  0.7  2.3
4  4  0.3  0.3  0.0  9.0  1.1  3.4
5  4  0.2  0.1  0.3  9.0  1.1  3.4
6  4  0.1  0.2  0.5  9.0  1.1  3.4

    pd.merge(df_one, df_two, on='A').apply(lambda s: sum([s['B%d'%i] * s['C%d'%i] for i in range(1, 4)]) , axis=1)
0    1.40
1    1.60
2    2.10
3    2.63
4    3.03
5    2.93
6    2.82
于 2013-07-15T19:35:11.023 回答
0

我会将这些行压缩在一起,并使用一个过滤器或一个只接受 A 列匹配的行的理解。

就像是

[scalar_product(a,b) for a,b in zip (frame1, frame2) if a[0]==b[0]]

假设您愿意为 scalar_product 填写适当的材料

(抱歉,如果我在这里提出了一个想法 - 此代码仅用于示例目的,尚未经过测试!)

于 2013-07-15T15:11:26.027 回答