【问题标题】:Pandas sum across columns and divide each cell from that valuePandas 跨列求和并将每个单元格与该值相除
【发布时间】:2014-12-19 16:46:26
【问题描述】:

我已经阅读了一个 csv 文件并将其转为以下结构:

pivoted = df.pivot('user_id', 'group', 'value')
lookup = df.drop_duplicates('user_id')[['user_id', 'group']]
lookup.set_index(['user_id'], inplace=True)
result = pivoted.join(lookup)
result = result.fillna(0) 

部分结果:

             0     1     2    3     4    5   6  7    8   9  10  11  12  13  group
user_id                                                                      
2        33653  2325   916  720   867  187  31  0    6   3  42  56  92  15    l-1
4        18895   414  1116  570  1190   55  92  0  122  23  78   6   4   2    l-2 
16        1383    70    27   17    17    1   0  0    0   0   1   0   0   0    l-2
50         396    72    34    5    18    0   0  0    0   0   0   0   0   0    l-3
51        3915  1170   402  832  2791  316  12  5  118  51  32   9  62  27    l-4

我想按每行对第 0 列到第 13 列求和,然后将每个单元格除以该行的总和。我还在习惯熊猫;如果我理解正确,我们应该在做这样的事情时尽量避免 for 循环?换句话说,我怎样才能以“熊猫”的方式做到这一点?

【问题讨论】:

  • 我想是的,更多的是 sudo:0/sum(0..13),1/sum(0..13) 还有column 0 是列的名称,而不是它的索引。`

标签: python pandas dataframe


【解决方案1】:

以下对我来说似乎工作正常:

In [39]:

cols = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13']
result[cols]  = result[cols].apply(lambda row: row / row.sum(axis=1), axis=1)
result

Out[39]:
                0         1         2         3         4         5         6  \
user_id                                                                         
2        0.864827  0.059749  0.023540  0.018503  0.022280  0.004806  0.000797   
4        0.837285  0.018345  0.049453  0.025258  0.052732  0.002437  0.004077   
16       0.912269  0.046174  0.017810  0.011214  0.011214  0.000660  0.000000   
50       0.754286  0.137143  0.064762  0.009524  0.034286  0.000000  0.000000   
51       0.401868  0.120099  0.041265  0.085403  0.286491  0.032437  0.001232   

                7         8         9        10        11        12        13  \
user_id                                                                         
2        0.000000  0.000154  0.000077  0.001079  0.001439  0.002364  0.000385   
4        0.000000  0.005406  0.001019  0.003456  0.000266  0.000177  0.000089   
16       0.000000  0.000000  0.000000  0.000660  0.000000  0.000000  0.000000   
50       0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000   
51       0.000513  0.012113  0.005235  0.003285  0.000924  0.006364  0.002772   

        group  
user_id        
2         l-1  
4         l-2  
16        l-2  
50        l-3  
51        l-4  

上面的ok,下面的会快很多:

result[cols]  = result[cols].div(result[cols].sum(axis=1), axis=0)

而且只是为了证明结果是一样的:

In [47]:

cols = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13']
np.alltrue(result[cols].div(result[cols].sum(axis=1), axis=0) == result[cols].apply(lambda row: row / row.sum(axis=1), axis=1))
Out[47]:
True

而且它更快:

In [48]:

cols = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13']
%timeit result[cols].div(result[cols].sum(axis=1), axis=0) 
%timeit result[cols].apply(lambda row: row / row.sum(axis=1), axis=1)
100 loops, best of 3: 2.38 ms per loop
100 loops, best of 3: 4.47 ms per loop

【讨论】:

  • 对不起,我想一直总结到第 13 列。有一个错字。
  • @Null-Hypothesis 我原来的答案是不正确的,现在已经更正了,我现在应用逐行将每个项目除以行总和,这些值现在对我来说似乎是正确的
  • 不这样做就没有其他办法提到所有列cols = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13']×评论只能编辑5分钟×评论只能编辑5分钟×评论只能编辑5分钟
  • 你可以用result.loc[:,'0':'13']替换列
  • 是的@Nanashi 这条线完成了工作df.loc[:,"value1":"value3"] = df.loc[:,"value1":"value3"].div(df.sum(axis=1),
【解决方案2】:

尝试以下方法:

In [1]: import pandas as pd

In [2]: df = pd.read_csv("test.csv")

In [3]: df
Out[3]: 
  id  value1  value2  value3
0  A       1       2       3
1  B       4       5       6
2  C       7       8       9

In [4]: df["sum"] = df.sum(axis=1)

In [5]: df
Out[5]: 
  id  value1  value2  value3  sum
0  A       1       2       3    6
1  B       4       5       6   15
2  C       7       8       9   24

In [6]: df_new = df.loc[:,"value1":"value3"].div(df["sum"], axis=0)

In [7]: df_new
Out[7]: 
     value1    value2  value3
0  0.166667  0.333333   0.500
1  0.266667  0.333333   0.400
2  0.291667  0.333333   0.375

或者您可以执行以下操作:

In [8]: df.loc[:,"value1":"value3"] = df.loc[:,"value1":"value3"].div(df["sum"], axis=0)

In [9]: df
Out[9]: 
  id    value1    value2  value3  sum
0  A  0.166667  0.333333   0.500    6
1  B  0.266667  0.333333   0.400   15
2  C  0.291667  0.333333   0.375   24

或者直接从头开始:

In [10]: df = pd.read_csv("test.csv")

In [11]: df
Out[11]: 
  id  value1  value2  value3
0  A       1       2       3
1  B       4       5       6
2  C       7       8       9

In [12]: df.loc[:,"value1":"value3"] = df.loc[:,"value1":"value3"].div(df.sum(axis=1), axis=0)

In [13]: df
Out[13]: 
  id    value1    value2  value3
0  A  0.166667  0.333333   0.500
1  B  0.266667  0.333333   0.400
2  C  0.291667  0.333333   0.375

value1 等列更改为标题应该类似。

【讨论】:

    【解决方案3】:

    更简单:

    result.div(result.sum(axis=1), axis=0)
    

    【讨论】:

      【解决方案4】:

      每列更容易工作:

      df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]])
      (df.T / df.T.sum()).T
      

      结果:

               0         1      2
      0  0.166667  0.333333  0.500
      1  0.266667  0.333333  0.400
      2  0.291667  0.333333  0.375
      

      【讨论】:

      • 更好的解决方案,非常低的内存消耗:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-06
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多