相互比较相应的列,并将结果存储在新列中

时间:2019-06-03 10:24:05

标签: python pandas dataframe

我有一个数据,我使用数据透视表方法进行了数据透视,现在数据如下所示:

rule_id  a   b   c
50211    8   0   0
50249    16  0   3
50378    0   2   0
50402    12  9   6

我已将'rule_id'设置为索引。现在,我将一列与其对应的列进行比较,并使用结果创建另一列。这个想法是,如果第一列的值不是0,第二列要与之比较的第二列的值为0,则应在新创建的列中更新100,但是如果情况相反,则'Null'应该更新。如果两个列都为0,则还应更新'Null'。如果最后一列的值为0,则应更新'Null',而不是0,则应更新100。但是,如果两列的值都不为0(例如数据的最后一行),则对a列和b列的比较应该像这样:

value_of_b/value_of_a *50 + 50

以及b和c列:

value_of_c/value_of_b *25 + 25

并且类似地,如果有更多列,则乘法和加法值应为12.5,依此类推。

除了最后的结果(除法和乘法)外,我能够实现上述所有目的。我使用了这段代码:

m = df.eq(df.shift(-1, axis=1))

arr = np.select([df ==0, m], [np.nan, df], 1*100)

df2 = pd.DataFrame(arr, index=df.index).rename(columns=lambda x: f'comp{x+1}')

df3 = df.join(df2)

df是存储我一开始提到的数据透视表数据的数据框。使用此代码后,我的数据如下所示:

   rule_id   a   b   c  comp1 comp2 comp3
    50211    8   0   0   100   NaN   NaN
    50249    16  0   3   100   NaN   100
    50378    0   2   0   NaN   100   NaN
    50402    12  9   6   100   100   100

但是我希望数据看起来像这样:

   rule_id   a   b   c  comp1 comp2 comp3
    50211    8   0   0   100   NaN   NaN
    50249    16  0   3   100   NaN   100
    50378    0   2   0   NaN   100   NaN
    50402    12  9   6   87.5  41.67 100

如果你们能帮助我获得所需的数据,我将不胜感激。

编辑: 这是我的数据的样子:

enter image description here

2 个答案:

答案 0 :(得分:1)

问题在于,在构建新的compx列时使用的系数不仅取决于列的位置。实际上,在每一行中,它将在每个0值之后重置为其最大值50,并且是非0值之后的前一个值的一半。那些 resetable 系列很难在大熊猫中矢量化,尤其是在行中。在这里,我将构建一个仅包含那些系数的伴随数据框,并直接使用numpy基础数组来尽可能高效地计算它们。代码可能是:

# transpose the dataframe to process columns instead of rows
coeff = df.T

# compute the coefficients
for name, s in coeff.items():
    top = 100              # start at 100
    r = []
    for i, v in enumerate(s):
        if v == 0:         # reset to 100 on a 0 value
            top=100
        else:
            top = top/2    # else half the previous value
        r.append(top)
    coeff.loc[:, name] = r # set the whole column in one operation

# transpose back to have a companion dataframe for df
coeff = coeff.T

# build a new column from 2 consecutive ones, using the coeff dataframe
def build_comp(col1, col2, i):
    df['comp{}'.format(i)] = np.where(df[col1] == 0, np.nan,
                                      np.where(df[col2] == 0, 100,
                                               df[col2]/df[col1]*coeff[col1]
                                               +coeff[col1]))

old = df.columns[0]          # store name of first column

# Ok, enumerate all the columns (except first one)
for i, col in enumerate(df.columns[1:], 1):
    build_comp(old, col, i)
    old = col                # keep current column name for next iteration

# special processing for last comp column
df['comp{}'.format(i+1)] = np.where(df[col] == 0, np.nan, 100)

使用此初始数据框:

date     2019-04-25 15:08:23  2019-04-25 16:14:14  2019-04-25 16:29:05  2019-04-25 16:36:32
rule_id
50402                      0                    0                    9                    0
51121                      0                    1                    0                    0
51147                      0                    1                    0                    0
51183                      2                    0                    0                    0
51283                      0                   12                    9                    6
51684                      0                    1                    0                    0
52035                      0                    4                    3                    2

它给出了预期的结果:

date     2019-04-25 15:08:23  2019-04-25 16:14:14  2019-04-25 16:29:05  2019-04-25 16:36:32  comp1  comp2       comp3  comp4
rule_id
50402                      0                    0                    9                    0    NaN    NaN  100.000000    NaN
51121                      0                    1                    0                    0    NaN  100.0         NaN    NaN
51147                      0                    1                    0                    0    NaN  100.0         NaN    NaN
51183                      2                    0                    0                    0  100.0    NaN         NaN    NaN
51283                      0                   12                    9                    6    NaN   87.5   41.666667  100.0
51684                      0                    1                    0                    0    NaN  100.0         NaN    NaN
52035                      0                    4                    3                    2    NaN   87.5   41.666667  100.0

答案 1 :(得分:0)

好吧,我认为您可以遍历数据帧List并使用if-else获得所需的输出。

df