【问题标题】:How to group by a column in pandas and apply a ifelse based on column values如何按熊猫中的列分组并根据列值应用 ifelse
【发布时间】:2018-06-28 06:39:11
【问题描述】:

我正在尝试按 pandas DataFrame 中的列进行分组并应用 ifelse 函数,该函数具有使用列值的测试,并根据测试返回不同的真值和假值。

我已经在 R 中使用 data.table 包轻松完成了这项工作,我基本上希望在 Python 中使用 pandas 实现这一点。

library(data.table)

dat <- data.table(
  i_n = c('a', 'b', 'b', 'd', 'e', 'f', 'g', 'h', 'h', 'i'),
  m_b_r = c(0, 1, 0, 0, 0, 0, 0, 1, 0, 0),
  o_q = c(1, 8, 8, 1, 1, 1, 1, 2, 2, 1),
  a_q = c(1, 5, 15, 1, 57, 1, 5, 1, 1, 1)
)

dat <- dat[, ('p_q') := ifelse(
  test =get('m_b_r') == 1,
  yes =get('a_q'),
  no =get('o_q') - data.table::shift(get('a_q'), n = 1L, type = 'lag', fill = 0 )
), by = 'i_n']

【问题讨论】:

标签: python r pandas if-statement data.table


【解决方案1】:

我相信需要numpy.whereDataFrameGroupBy.shift

shifted = dat.groupby('i_n')['a_q'].shift().fillna(0)
dat['p_q'] = np.where(dat['m_b_r'] == 1, dat['a_q'], dat['o_q'] - shifted)
print (dat)
  i_n  m_b_r  o_q  a_q  p_q
0   a      0    1    1  1.0
1   b      1    8    5  5.0
2   b      0    8   15  3.0
3   d      0    1    1  1.0
4   e      0    1   57  1.0
5   f      0    1    1  1.0
6   g      0    1    5  1.0
7   h      1    2    1  1.0
8   h      0    2    1  1.0
9   i      0    1    1  1.0

有可能调用自定义函数,但更快的是第一个解决方案:

def f(x):
    x['p_q'] = np.where(x['m_b_r'] == 1, x['a_q'], x['o_q'] - x['a_q'].shift().fillna(0))
    return x

df = dat.groupby('i_n').apply(f)
print (df)
  i_n  m_b_r  o_q  a_q  p_q
0   a      0    1    1  1.0
1   b      1    8    5  5.0
2   b      0    8   15  3.0
3   d      0    1    1  1.0
4   e      0    1   57  1.0
5   f      0    1    1  1.0
6   g      0    1    5  1.0
7   h      1    2    1  1.0
8   h      0    2    1  1.0
9   i      0    1    1  1.0

【讨论】:

    【解决方案2】:

    或者python中的tidyverse方式:

    >>> from datar.all import c, f, tibble, group_by, mutate, if_else, lag
    >>> 
    >>> dat = tibble(  
    ...     i_n = c('a', 'b', 'b', 'd', 'e', 'f', 'g', 'h', 'h', 'i'),  
    ...     m_b_r = c(0, 1, 0, 0, 0, 0, 0, 1, 0, 0),  
    ...     o_q = c(1, 8, 8, 1, 1, 1, 1, 2, 2, 1),  
    ...     a_q = c(1, 5, 15, 1, 57, 1, 5, 1, 1, 1)  
    ... ) 
    >>> 
    >>> dat >> group_by(f.i_n) >> mutate(
    ...     p_q=if_else(
    ...         f.m_b_r == 1, 
    ...         f.a_q, 
    ...         f.o_q - lag(f.a_q, default=0)
    ...     )
    ... )
           i_n   m_b_r     o_q     a_q     p_q
      <object> <int64> <int64> <int64> <int64>
    0        a       0       1       1       1
    1        b       1       8       5       5
    2        b       0       8      15       3
    3        d       0       1       1       1
    4        e       0       1      57       1
    5        f       0       1       1       1
    6        g       0       1       5       1
    7        h       1       2       1       1
    8        h       0       2       1       1
    9        i       0       1       1       1
    
    [Groups: i_n (n=8)]
    

    我是datar 包的作者。如果您有任何问题,请随时提交问题。

    【讨论】:

      猜你喜欢
      • 2021-01-22
      • 1970-01-01
      • 2016-07-07
      • 2021-11-18
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      相关资源
      最近更新 更多