根据三列的值有条件地交互式计算列

Conditionally and interatively calculate column based on value of three columns

我是运行Windows10,Python2.7通过SpyderIDE.

我有一个 pandas DataFramedf:

df = pd.DataFrame({'fld1': ['x', 'x', 'x','y','y','y','z','z']
                , 'fld2': ['x', 'y', 'z','x','y','z','x','y']
                , 'relationship': [.25,.25,.50,.33,.33,.33,.5,.5]})

df
 Out[172]: 
  fld1 fld2  relationship
 0    x    x          0.25
 1    x    y          0.25
 2    x    z          0.50
 3    y    x          0.33
 4    y    y          0.33
 5    y    z          0.33
 6    z    x          0.50
 7    z    y          0.50

我想构建一个 function 来迭代 Dataframe df 的行以在 df.

中生成一个新列

此函数将开始于:

第 1 步:relationship 列,其中 fld1 = xfld2 = x然后

第 2 步: 检查 fld1 = x 的情况下是否有更多唯一值 fld2

第 3 步: 如果 fld2 的另一个唯一值与 fld1 = x 关联(在这两个更唯一的值中存在,xy),将 步骤 1 中的 relationship 值添加到 fld1relationship 列= xfld2 的下一个唯一值(在本例中 fld2 = y 是下一个唯一值)乘以关系的倒数(在本例中 fld1 = yfld2 = x)

第 4 步: 重复 第 2 步,直到 fld2 的所有唯一值与 fld1 = x这样算出来的

步骤 4: 重复 步骤 1 以获得 fld1 的下一个唯一值。在这种情况下,它将是 fld1 = y

为了以另一种方式解释此功能逻辑,下面是在 excel 中如何完成此操作的示例:

        A       B         C             D
   1    fld1    fld2      relationship  Connection
   2    x        x         0.25         =C2+(C3*C5)+(C4*C8)
   3    x        y         0.25         =C3+(C4*C9)
   4    x        z         0.5          =C4+(C3*C7)
   5    y        x         0.33         =C5+(C7*C8)
   6    y        y         0.33         =C6+(C5*C3)+(C7*C9)
   7    y        z         0.33         =C7+(C5*C4)
   8    z        x         0.5          =C8+(C9*C5)
   9    z        y         0.5          =C9+(C8*C4)

该函数的输出应产生一个 Dataframe 与下面的 df2 相同的结果:

df2 = pd.DataFrame({'fld1': ['x', 'x', 'x','y','y','y','z','z']
            , 'fld2': ['x', 'y', 'z','x','y','z','x','y']
            , 'relationship': [.25,.25,.50,.33,.33,.33,.5,.5]
            , 'connection':     [.5825,0.5,0.5825,0.495,0.5775,0.495,0.665,0.75]})

df2
Out[174]: 
    connection fld1 fld2  relationship
0      0.5825    x    x          0.25
1      0.5000    x    y          0.25
2      0.5825    x    z          0.50
3      0.4950    y    x          0.33
4      0.5775    y    y          0.33
5      0.4950    y    z          0.33
6      0.6650    z    x          0.50
7      0.7500    z    y          0.50

好了,这就是解决您问题的一种方法。我用字典来保存每个组合的值。

xyzdict = {"xx":0.25,
          "xy":0.25,
          "xz":0.5,
          "yx":0.33,
          "yy":0.33,
          "yz":0.33,
          "zx":0.5,
          "zy":0.5}

然后,对于每个 'connection' 组合,第一个字母始终与 fld1 的第一个字母相同。第二个字母总是 not fld1。因此,这是一种详尽且可能不是 pythonic 的方法来计算您的值并将组合的连接值存储在字典中供以后使用。

cnxn = {}
xyz = ["x","y","z"]

for combo in xyzdict.keys():
    #print "the combo is %s" % (combo) #xyzdict[two] #actual value
    first_letter = combo[0]

    not_second = [combo[0],combo[1]]
    not_second_letter = list(set(xyz) - set(not_second))

    if len(not_second_letter) > 1:
        multi_cnxn = []
        for each_not_second_letter in not_second_letter:

            fwd = ''.join((first_letter,each_not_second_letter))
            rev = ''.join((each_not_second_letter,first_letter))
            cnxnval = xyzdict[fwd] * xyzdict[rev]

            multi_cnxn.append(cnxnval)

        rowvalue = xyzdict[combo] + sum(multi_cnxn)
        cnxn[combo] =rowvalue
    else:
        fwd = ''.join((first_letter,not_second_letter[0]))
        rev = ''.join((not_second_letter[0],first_letter))
        cnxnval = xyzdict[fwd] * xyzdict[rev]

        rowvalue = xyzdict[combo] + cnxnval
        cnxn[combo] = rowvalue

差不多了,定义一个函数check,它将提取你的fld1fld2和return上面cnxn的计算值。

def check(fld1,fld2,cnxn_sub):
    rowpair = ''.join((fld1,fld2))
    return cnxn_sub[rowpair]

最后,pandas apply 把它全部带回家。

df['connection'] = df.apply(lambda row: check(row['fld1'], row['fld2'],cnxn), axis=1)

这是我的结果,我们的 "yz" 连接有点断,不知道是你的还是我的...

fld1    fld2    relationship    connection
0   x   x   0.25    0.5825
1   x   y   0.25    0.5000
2   x   z   0.50    0.5825
3   y   x   0.33    0.4950
4   y   y   0.33    0.5775
5   y   z   0.33    0.4125
6   z   x   0.50    0.6650
7   z   y   0.50    0.7500

祝你好运!