【问题标题】:Pandas multiindex dataframe set first row in a column to 0Pandas 多索引数据框将列中的第一行设置为 0
【发布时间】:2014-10-05 20:12:45
【问题描述】:

我在处理 pandas 中的分组对象时遇到了一些问题。具体来说,我希望能够将列中的第一行设置为 0,同时保持其他行不变。

例如:

df = pd.DataFrame({'A': ['foo', 'bar', 'baz'] * 2,
                        'B': rand.randn(6),
                        'C': rand.rand(6) > .5})

给我

    A         B      C
0  foo  1.624345  False
1  bar -0.611756   True
2  baz -0.528172  False
3  foo -1.072969   True
4  bar  0.865408  False
5  baz -2.301539   True

我将它们按 A 分组并按 B 排序:

f = lambda x: x.sort('B', ascending=True)
sort_df = df.groupby('A',sort=False).apply(f)

得到这个:

         A         B      C
    A                          
foo 3  foo -1.072969   True
    0  foo  1.624345  False
bar 1  bar -0.611756   True
    4  bar  0.865408  False
baz 5  baz -2.301539   True
    2  baz -0.528172  False

现在我有了组,我希望能够将每个组中的第一个元素设置为 0。我该怎么做?

这样的事情会起作用,但我想要一种更优化的方法:

for group in sort_df.groupby(level=0).groups:
    sort_df.loc[(group,sort_df.loc[group].index[0]),'B']=0

任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: python pandas multi-index split-apply-combine


    【解决方案1】:

    这是执行此操作的矢量化方式。会更快

    In [26]: pd.set_option('max_rows',10)
    

    创建具有2级多索引的框架,按A排序(此处任意)

    In [27]: df = DataFrame(dict(A = np.random.randint(0,100,size=N),B=np.random.randint(0,100,size=N),C=np.random.randn(N))).sort(columns=['A'])
    
    In [28]: df
    Out[28]: 
            A   B         C
    61474   0  40 -0.731163
    82386   0  18 -1.316136
    63372   0  28  0.112819
    49666   0  13 -0.649491
    31631   0  89 -0.835208
    ...    ..  ..       ...
    42178  99  28 -0.029800
    59529  99  31 -0.733588
    13503  99  60  0.672754
    20961  99  18  0.252714
    31882  99  22  0.083340
    
    [100000 rows x 3 columns]
    

    重置索引以捕获索引值。根据B找到第一个值

    In [29]: grouped = df.reset_index().groupby('B').first()
    
    In [30]: grouped
    Out[30]: 
        index  A         C
    B                     
    0   26576  0  1.123605
    1   38311  0  0.128966
    2   45135  0 -0.039886
    3   38434  0 -1.284028
    4   82088  0 -0.747440
    ..    ... ..       ...
    95  82620  0 -1.197625
    96  63278  0 -0.625400
    97  23226  0 -0.497609
    98  82520  0 -0.828773
    99  35902  0 -0.199752
    
    [100 rows x 3 columns]
    

    这会给你一个进入框架的索引器。

    In [31]: df.loc[grouped['index']] = 0
    
    In [32]: df
    Out[32]: 
            A   B         C
    61474   0   0  0.000000
    82386   0   0  0.000000
    63372   0   0  0.000000
    49666   0   0  0.000000
    31631   0   0  0.000000
    ...    ..  ..       ...
    42178  99  28 -0.029800
    59529  99  31 -0.733588
    13503  99  60  0.672754
    20961  99  18  0.252714
    31882  99  22  0.083340
    
    [100000 rows x 3 columns]
    

    如果你愿意

    In [33]: df.sort_index()
    Out[33]: 
            A   B         C
    0      40  56 -1.223941
    1      24  77 -0.039775
    2       7  83  0.741013
    3      48  38 -1.795053
    4      62  15 -2.734968
    ...    ..  ..       ...
    99995  20  25 -0.286300
    99996  27  21 -0.120430
    99997   0   4  0.607524
    99998  38  31  0.717069
    99999  33  63 -0.226888
    
    [100000 rows x 3 columns]
    

    这个方法

    In [34]: %timeit df.loc[grouped['index']] = 0
    100 loops, best of 3: 7.33 ms per loop
    

    你的原创

    In [37]: %timeit df.groupby('A',sort=False).apply(f)
    10 loops, best of 3: 109 ms per loop
    

    如果你有更多的组,这种性能差异将会扩大。

    【讨论】:

    • 这非常快!除了做 x.iloc[:,column_name] 之外,有没有类似的方法来索引一个组的所有元素?
    • 不确定您的意思。请提出一个新问题(或编辑以显示示例)
    【解决方案2】:

    你已经在应用一个函数来做一些工作。为什么不把它包括在内?

    而不是使用

    lambda f: ...
    

    只需使用:

    def f(x):
        x = x.sort('B', ascending=True)
        x.iloc[0, 1] = 0
        return x
    
    sort_df = df.groupby('A',sort=False).apply(f)
    

    【讨论】:

      【解决方案3】:

      这是您要找的吗?

      sort_df.B[::2]=0
      

      例如:

      sort_df
      
                A         B      C
      A                          
      foo 0  foo  0.192347   True
          3  foo  0.295985   True
      bar 1  bar  0.012400  False
          4  bar  0.628488   True
      baz 5  baz  0.180934   True
          2  baz  0.328735   True
      
      
      sort_df.B[::2]=0
      
      sort_df
               A         B      C
      A                          
      foo 0  foo  0.000000   True
          3  foo  0.295985   True
      bar 1  bar  0.000000  False
          4  bar  0.628488   True
      baz 5  baz  0.000000   True
          2  baz  0.328735   True
      

      仅当 all(df.A.value_counts()==df.A.value_counts()[0]) 为 True 时才有效。

      【讨论】:

      • 这是虚拟数据 - 对于我的真实情况,条件不成立。
      猜你喜欢
      • 1970-01-01
      • 2017-05-16
      • 2021-12-31
      • 1970-01-01
      • 2016-05-21
      • 2019-04-14
      • 2017-10-23
      • 2020-12-13
      • 2017-02-06
      相关资源
      最近更新 更多