【问题标题】:Specify number of columns consulted in reversed(row) function指定 reversed(row) 函数中查询的列数
【发布时间】:2021-08-25 11:31:28
【问题描述】:

上下文

我的 df 类似于:

df_a = pd.DataFrame({
    '2020_Q1': [2, 3, 6, 20, 20],
    '2020_Q2': [2, 3, 6, 20, 20],
    '2020_Q3': [5, 3, 6, 20, 20], 
    '2020_Q4': [5, 4, 7, 20, 20],
    '2021_Q1': [5, 3, 7, 20, 20],
    '2021_Q2': [5, 4, 0, 20, 20],
}, index = ['People', 'AA', 'BB', 'MM', '$$'])
df_a.columns = pd.to_datetime(df_a.columns).to_period('Q')
df_a

Out[1]: 
          2020Q1   2020Q2   2020Q3  2020Q4   2021Q1   2021Q2
People        2        2        5        5        5        5
AA            3        3        3        4        3        4
BB            6        6        6        7        7        0
MM           20       20       20       20       20       20
$$           20       20       20       20       20       20

还有一个函数,它根据每行的计算方式设置年终值。 df['People', 'AA', 'BB'] 的行在一年的最后一个季度计算,其值大于零,如果没有更高的值则为零,财务值 df['MM', '$$'] 计算为一年中的季度的SUM

def compute_end_year_value(row):
    if row.name in ['People', 'AA', 'BB']:
        for val in reversed(row):
            if val > 0:
                return val
        return 0
    return sum(row)

问题

但是,如果我按原样运行该函数,它将查询整个行。如何在定义中添加一种方法来指定反转函数以仅考虑插入它的最后 n 列?

所以当我执行以下代码时,我会得到该输出

df_a.insert(4,'2020_Total', df_a.apply(compute_end_year_value, axis = 1, steps = 4))
df_a.insert(7,'2021_Total', df_a.apply(compute_end_year_value, axis = 1, steps = 2))
df_a 

Out[1]: 
         2020Q1   2020Q2   2020Q3   2020Q4   2020_Total   2021Q1  2021Q2  2021_Total
People        2        2        5        5           5        5        5           5
AA            3        3        3        4           4        3        4           4
BB            6        6        6        6           6        7        0           7
MM           20       20       20       20          80       20       20          40
$$           20       20       20       20          80       20       20          40
           

【问题讨论】:

  • 您的 df 似乎在概念上被转置了

标签: python pandas dataframe calculated-columns


【解决方案1】:

您在应用函数中迭代行而不是列。

要实现所需的结果,您需要将轴指定为列。

df_a.insert(4,'2020_Total', df_a.apply(lambda col: compute_end_year_value(col), axis=1))
df_a.insert(7,'2021_Total', df_a.apply(lambda col: compute_end_year_value(col), axis=1))

>>>
        2020_Q1  2020_Q2  2020_Q3  2020_Q4  2020_Total  2021_Q1  2021_Q2  \
People        2        2        5        5           5        5        5   
AA            3        3        3        4           4        3        4   
BB            6        6        6        7           7        7        0   
MM           20       20       20       20         120       20       20   
$$           20       20       20       20         120       20       20   

        2021_Total  
People           5  
AA               4  
BB               7  
MM             240  
$$             240  

有关应用功能的更多信息,请参阅docs

编辑

为了处理每一年,我认为最简单的方法是告诉函数要考虑哪一年。我将compute_end_year_value 方法修改为:

def compute_end_year_value(row,year):
    col_pos_year = [col.startswith(year) for col in df_a.columns]
    valid_year_columns = df_a.columns[col_pos_year]
    row = row[valid_year_columns]
    if row.name in ['People', 'AA', 'BB']:
          for val in reversed(row):
              if val > 0:
                  return val
          return 0
    
    return sum(row)

df_a.insert(4,'2020_Total', df_a.apply(lambda col: compute_end_year_value(col, "2020"), axis=1))
df_a.insert(7,'2021_Total', df_a.apply(lambda col: compute_end_year_value(col, "2021"), axis=1))
df_a
>>>
        2020_Q1  2020_Q2  2020_Q3  2020_Q4  2020_Total  2021_Q1  2021_Q2  \
People        2        2        5        5           5        5        5   
AA            3        3        3        4           4        3        4   
BB            6        6        6        7           7        7        0   
MM           20       20       20       20          80       20       20   
$$           20       20       20       20          80       20       20   

        2021_Total  
People           5  
AA               4  
BB               7  
MM              40  
$$              40  

我添加了一个列表,用于检查列是否从特定年份开始并仅选择要迭代的那些列。

【讨论】:

  • 感谢@Oddaspa,但是这个建议的解决方案将所有值添加到 2021_Total 行中(240,当它应该是列 2021_Q1 和 2021_Q2(40)的总和时。我需要指定多少该计算必须考虑列 [totals_column 的左侧]。
  • 我已经用建议的解决方案更新了代码。
  • 这太完美了!谢谢....现在我无法实现这一点,因为数据集的列在日期时间。我没有提到这一点,因为我认为这将是一个简单的替换,但事实证明它比我最初预期的要复杂。
  • 您可以使用日期时间具有的.year 变量。它以字符串格式为您提供日期时间的年份。所以不是col.startswith(year),而是col.year == year
  • 谢谢,我发现它也可以与valid_year_columns = df_a.T[year].T.columns 一起使用。但是重要的是,在应用该函数时,它不会链接在.insert() 中,因为字符串中的前一年列名会破坏该函数。我只是通过独立运行函数并创建自己的 df 然后加入 df_a 来修复它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
  • 1970-01-01
相关资源
最近更新 更多