【问题标题】:Compare multiple columns of a dataframe and store the result in a new column比较数据框的多列并将结果存储在新列中
【发布时间】:2019-06-07 17:45:20
【问题描述】:

我的数据看起来像这样(我已将 'rule_id' 设置为索引):

rule_id  a   b   c  d
50378    2   0   0  5
50402    12  9   6  0
52879    0   4   3  2

使用此代码后:

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


        conditions = [(df[col1] == 0) & (df[col2] == 0), (df[col1] != 0) & (df[col2] == 0), (df[col1] == df[col2]),
                      (df[col1] != 0) & (df[col2] != 0)]

        choices = [np.nan , 100 , coeff[col1] , df[col2]/df[col1]*coeff[col1]+coeff[col1]]

        df['comp{}'.format(i)] = np.select(conditions , choices)

    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)

我的数据如下所示:

rule_id  a   b   c  d  comp1  comp2  comp3  comp4
50378    2   0   0  5   100    NaN    NaN    100
50402    12  9   6  0   87.5   41.66  100    NaN
52879    0   4   3  2   NaN    87.5  41.66  100 

所以这里的“df”是存储我上面提到的数据的数据框。 看第一行。根据我的代码,如果比较两列并且第一列具有非零值(2)并且第二列具有 0 ,那么 100 应该在新列中更新,我能够实现,如果有多个非零值之间的比较(看第2行),那么比较是这样的:

9/12 *50 +50 = 87.5

然后

6/9 * 25 + 25 = 41.66

我能够实现,但列 'c' 和值 6 和 0 之间的 'd' 之间的第三个比较应该是:

0/6 *12.5 + 12.5 = 12.5

我在实现时遇到了问题。因此,第 2 行 comp3 中的值应该是 12.5,而不是 100。最后一行也是如此,其中值为 4 ,3 和 2

这是我想要的结果:

rule_id  a   b   c  d  comp1  comp2  comp3  comp4
50378    2   0   0  5   100    NaN    NaN    100
50402    12  9   6  0   87.5   41.66  12.5   NaN
52879    0   4   3  2   NaN    87.5  41.66   12.5 

【问题讨论】:

  • 您好,这很难理解...您能否尝试创建一个无法按预期工作的最小示例?
  • 好的,当然。我将编辑我的问题
  • 嗨@Joël,我已经编辑了我的问题,请看一下
  • 谢谢,更清楚了;你能再次发布预期的内容吗?
  • 我已根据您@Joël 的评论更新了我的问题。

标签: python pandas dataframe


【解决方案1】:

你说:

列 'c' 和 'd' 之间的第三个比较在值 6 和 0 之间应该是:

0/6 *12.5 + 12.5 = 12.5

但是你的代码说:

   conditions = [(df[col1] == 0) & (df[col2] == 0), (df[col1] != 0) & (df[col2] == 0), (df[col1] == df[col2]),
                  (df[col1] != 0) & (df[col2] != 0)]

   choices = [np.nan , 100 , coeff[col1] , df[col2]/df[col1]*coeff[col1]+coeff[col1]]

显然(6, 0) 满足condition[1] 并因此产生100。您似乎认为它应该满足condition[3],即两者都不为零,但(6, 0) 不满足该条件,即使满足也无所谓,因为首先匹配condition[1],然后np.select()选择第一个匹配项。

也许你想要这样的东西:

    conditions = [(df[col1] == 0) & (df[col2] == 0), (df[col1] == df[col2])]
    choices = [np.nan , coeff[col1]]
    default = df[col2]/df[col1]*coeff[col1]+coeff[col1]

    df['comp{}'.format(i)] = np.select(conditions , choices, default)

【讨论】:

  • 是的,这就是问题所在。我不知道如何克服它
  • @vesuvius:我现在提供了一个可能的解决方案。
  • 它可以工作,但默认的问题是,如果 col1 !=0 和 col2 ==0 ,假设 col1 是 2 并且 col2 是 0 ,那么结果将是 0/2 * 50 + 50这将是 50,但在这种情况下我想要 100。看看我的第一行数据
  • 如果是(2, 0),你想要100,但如果是(6, 0),你想要复杂的公式?标准是什么,你需要准确描述(2, 0)案例与(6, 0)案例的区别,或者你在问不可能。
  • 这不是关于 (2,0) 和 (6,0) 的,只是这样,看第一行,只有 1 个非零值 (2) 并且没有非在它之前的零值但在第二行中,值为 12 9 6 0 ,因此在 6 之前存在一个非零值(9),所以在这种情况下,我需要应用复杂的公式。基本上,我想如果有非零和0值之间的比较,它应该首先检查前一列是否有非零值,如果有,然后应用复数公式,否则100
【解决方案2】:

只是为了参与,这里是对您的代码的贡献,用于定义 coeff 矩阵,其中计算直接在整个列上执行。

初始化:

>>> df = pd.DataFrame([[2, 0, 0, 5], [12, 9, 6, 0], [0, 4, 3, 2]],
...                    index=[50378, 50402, 52879],
...                    columns=['a', 'b', 'c', 'd'])
>>> df 
        a   b   c   d
50378   2   0   0   5
50402   12  9   6   0
52879   0   4   3   2

然后计算系数:

>>> # taking care of coefficients, using direct computation on columns
>>> coeff2 = pd.DataFrame(index=df.index, columns=df.columns)
>>> top = pd.Series([100]*len(df.index), index=df.index)
>>> for col_name, col in df.iteritems():  # loop over columns
...     eq0 = (col==0)             # boolean serie, identifying rows where content is 0
...     top[eq0] = 100             # where `eq0` is `True`, set 100...
...     top[~eq0] = top[~eq0] / 2  # ... and divide others by 2
...     coeff2[col_name] = top     # assign to output
>>> coeff2

这给出了:

        a   b   c     d
50378   50  100 100   50
50402   50  25  12.5  100
52879   100 50  25    12.5

(对于您的问题的核心,John 确定了函数中缺少条件,因此无需我参与。)

【讨论】:

  • 嗨@Joel,你能加入聊天吗?我已经添加了我的代码,但我收到了一个错误,我已经在聊天中解释了所有内容,你会看看吗?
猜你喜欢
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
相关资源
最近更新 更多