【问题标题】:How to sum a single column values based on values in other column?如何根据其他列中的值对单列值求和?
【发布时间】:2021-01-09 15:22:34
【问题描述】:

我有以下 pandas DataFrame df:

      fea1  fea2       
0     a_1   1     
1     a_2   2      
2     a_4   3      
3     a_8   7      
4     u     9
5     be_1  5      
6     a_3   24     
7     a_5   5      
8     a_6   8
9     be_4  6
9     a_10  9
10    be_3  1
11    be_2  4
12    be_5  3
13    be_6  2

我需要将 a_1、a_2、a_3 的“fea2”值(例如 1、2、24)相加并保存为 a_q1,然后将 a_4、a_5、a_6 的“fea2”值相加并保存为 a_q2。此外,对于 be_1、be_2 和 be_3 等也是如此。像下面这样,

      fea1   fea2  
0     a_q1   27      
1     a_q2   16      
2     a_8    7
3     be_q1  10
4     be_q2  11    
5     u      9   

我试过了

df.groupby(df['fea1'].str.extract(r'^(\D+)', expand=False))['fea2'].sum().reset_index()

但它将所有 a_1、a_2、a_3、a_4、... 总结为一个值,并将 be_1、be_2、be_3、be_4 总结为...一个值。 如何有效地做到这一点?

【问题讨论】:

  • 好的,我如何确定是否需要将 3 个值或 4 个值组合在一起?
  • 那么下划线后面的数字是否没有空格。这意味着可以按任何顺序从 1 到 20 所有数字都存在并且只存在一次?
  • 我希望它有类似的宿舍。例如,第四季度:a_1、a_2、a_3。此外,下划线后没有空格。是的,这些数字只存在一次。
  • 不。它们只是从 1 到 27 的数字。

标签: python pandas sum


【解决方案1】:

IIUC你需要先在fea1sort,然后在上面创建一个组号,这样你就可以groupby

df = df.sort_values("fea1")

df["group"] = df.groupby(df["fea1"].str[0]).cumcount()//3

print (df.groupby([df["fea1"].str[0], "group"])["fea2"].sum())

fea1  group
a     0        27
      1        16
      2         7
u     0         9

【讨论】:

  • 谢谢。但是当我有像 a_10、a_20 这样的值时,就会出现问题。因为它将 fea1 排序为 a_1, a_10, a_11, ..........a_19, a_2, a_20,...
【解决方案2】:

让我们试试这个:

df[['Letters', 'number']] = df['fea1'].str.extract('(?P<letters>[a-zA-Z]+)_?(?P<number>\d+)?')
df['grp'] = (df['number'].fillna(0).astype(int) - 1) // 3

df_q = df.groupby(['Letters', 'grp'])['fea2'].sum()
df_q.index = [f'{i}_q{j+1}' if j != -1 else f'{i}' for i, j in df_q.index]
df_q

输出:

a_q1     27
a_q2     16
a_q3      7
a_q4      9
be_q1    10
be_q2     9
u         9
Name: fea2, dtype: int64

详情:

  • 使用字符串访问器、.strextract 以及用于命名捕获的正则表达式 组。
  • 现在,让我们使用一个小数学来使用除数 3 对行进行分组
  • 接下来,使用groupbysum
  • 最后使用列表推导展平多索引标头 f 字符串格式。

【讨论】:

  • 太棒了!有用。谢谢你。还有一个问题。那么,如果某些值有 a_s1、a_s2、a_s3、... 希望只有很小的变化。
  • 是的,需要修改正则表达式。正则表达式还是不是特别好学,但是非常好用。
  • 您希望字母只是“a”还是“a_s”?
  • 这里我只是陈述了一些价值观。但我有更多这样的值,有些值就像 a_s1、a_s2、a_s3。这就是为什么想要它作为'a_s'
【解决方案3】:

感谢@Scott Boston 的帮助。我改变了一点,效果很好。所以,我在这里发布完整的代码和你的代码。

data = {'fea1':['a_1', 'a_2', 'a_4', 'a_8', 'u', 'a_3', 'a_5', 'a_6', 'a_10', 'a_20','be_1','be_2','be_3','r_s1','r_s2'], 'fea2':[1, 2,3,7,9,24,5,8,3,7,1,8,4,1,2]} 

# Create DataFrame 
df = pd.DataFrame(data)

df['fea1'] = df['fea1'].str.replace('_', '')
df[['Letters', 'number']] = df['fea1'].str.extract('(?P<letters>[a-zA-Z]+)?(?P<number>\d+)?')
df['grp'] = (df['number'].fillna(0).astype(int) - 1) // 3
df_q = df.groupby(['Letters', 'grp'])['weight'].sum()
df_q.index = [f'{i}_q{j+1}' if j != -1 else f'{i}' for i, j in df_q.index]
df_q  #series

# converting series as dataframe
dff = pd.DataFrame({'fea1':df_q.index, 'fea2':df_q.values})
dff

【讨论】:

    猜你喜欢
    • 2014-05-07
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    • 2020-11-12
    • 2020-09-17
    • 2020-05-24
    相关资源
    最近更新 更多