【问题标题】:How to rename elements of a column based on conditional statements?如何根据条件语句重命名列的元素?
【发布时间】:2013-09-06 01:23:13
【问题描述】:

在 pandas 中,给定这个数据框:

df = pd.DataFrame({'l':['a','b','a','c','b','b','a','b','b','a'], 'v':['x','x','y','y','y','x','x','y','x','y'],'n':[1,2,1,2,2,1,2,1,1,2], 'g':[0,0,0,0,0,1,1,1,1,1]})

根据应用于数据框的一些条件语句重命名v 的元素的最佳解决方案是什么?

基本上,对于每一行(无论是g == 0 还是g == 1):

if df.l==a and df.n==1:
    df.v='val1'
elif df.l==a and df.n==2:
    df.v='val2'
elif df.l==b and df.n==1:
    df.v='val3'
elif df.l==b and df.n==2:
    df.v='val4'

【问题讨论】:

    标签: python pandas dataframe conditional-statements


    【解决方案1】:

    你可以简单地用布尔掩码写出来:

    df.loc[(df.l == 'a') & (df.n == 1), 'v'] = 'val1'
    df.loc[(df.l == 'a') & (df.n == 2), 'v'] = 'val2'
    df.loc[(df.l == 'b') & (df.n == 1), 'v'] = 'val3'
    df.loc[(df.l == 'b') & (df.n == 2), 'v'] = 'val4'
    
    In [11]: df
    Out[11]:
       g  l  n     v
    0  0  a  1  val1
    1  0  b  2  val4
    2  0  a  1  val1
    3  0  c  2     y
    4  0  b  2  val4
    5  1  b  1  val3
    6  1  a  2  val2
    7  1  b  1  val3
    8  1  b  1  val3
    9  1  a  2  val2
    

    更一般地说,您可以使用enumerate 和itertools.product(类似于菲利普的回答):

    from itertools import product
    lhs_values, rhs_values = ['a', 'b'], [1, 2]
    for i, (lhs, rhs) in enumerate(product(lhs_values, rhs_values)):
        df.loc[(df.l == lhs) & (df.n == rhs), 'v'] = 'val%s' % (i + 1)
    

    也许您只需要使用唯一的列值:

    for i, (lhs, rhs) in enumerate(product(df.l.unique(), df.n.unique())):
        df.loc[(df.l == lhs) & (df.n == rhs), 'v'] = 'val%s' % (i + 1)
    
    In [21]: df
    Out[21]:
       g  l  n     v
    0  0  a  1  val1
    1  0  b  2  val4
    2  0  a  1  val1
    3  0  c  2  val6
    4  0  b  2  val4
    5  1  b  1  val3
    6  1  a  2  val2
    7  1  b  1  val3
    8  1  b  1  val3
    9  1  a  2  val2
    

    【讨论】:

      【解决方案2】:

      我不确定您是否只是在给出示例 DataFrame 或者这是您的实际 DataFrame,但您的条件是一个笛卡尔积,您可以使用 itertools 构造它并循环左右手边,以及那对的替代品。

      from itertools import product
      
      lhs_values = 'a', 'b'
      rhs_values = 1, 2
      rep_values = ['val%d' % d for d in range(1, 5)]
      
      lhs_rhs = list(product(lhs_values, rhs_values))
      it = zip(*(zip(*lhs_rhs) + [tuple(rep_values)]))
      
      for lhs, rhs, rep in it:
          df.v[(df.l == lhs) & (df.n == rhs)] = rep
      

      【讨论】:

      • 仅供参考,可能有更易读的方法来做到这一点zip 疯狂。
      • 更简洁的解决方案是枚举(避免所有 zippy-ness):)
      【解决方案3】:

      使用map 的不同方法:

      value_map = {
                   ('a', 1): 'val1',
                   ('a', 2): 'val2',
                   ('b', 1): 'val3',
                   ('b', 2): 'val4'
                  }
      
      df.v = map(value_map.get, zip(df.l, df.n))
      

      编辑:Phillip Cloud 评论之后的另一种选择:如果您想保留原始 df.v 值以防字典中没有匹配项,您可以这样做:

      df.v = map(lambda x, y, z: value_map.get((x, y), z), df.l, df.n, df.v)
      

      【讨论】:

      • +1 非常优雅。您将如何处理 OP 希望保留已有内容的情况?
      • @PhillipCloud 嗯,没想到。用替代方法编辑。
      • 你也不需要zip,因为你只是在lambda的参数列表中解压它:map(lambda x, y, z: value_map.get((x, y), z), df.l, df.n, df.v)。
      猜你喜欢
      • 2021-04-23
      • 1970-01-01
      • 2022-01-17
      • 2014-10-25
      • 2019-09-30
      • 2020-05-03
      • 2017-08-15
      • 2012-02-26
      • 1970-01-01
      相关资源
      最近更新 更多