복붙노트

[PYTHON] MultiIndex pandas DataFrame의 하위 집합을 업데이트하는 방법

PYTHON

MultiIndex pandas DataFrame의 하위 집합을 업데이트하는 방법

MultiIndexed pandas DataFrame을 사용 중이며 DataFrame의 하위 집합에 특정 숫자를 곱하고 싶습니다.

이것은 MultiIndex와 동일하지만 동일합니다.

>>> d = pd.DataFrame({'year':[2008,2008,2008,2008,2009,2009,2009,2009], 
                      'flavour':['strawberry','strawberry','banana','banana',
                      'strawberry','strawberry','banana','banana'],
                      'day':['sat','sun','sat','sun','sat','sun','sat','sun'],
                      'sales':[10,12,22,23,11,13,23,24]})

>>> d = d.set_index(['year','flavour','day'])                  

>>> d
                     sales
year flavour    day       
2008 strawberry sat     10
                sun     12
     banana     sat     22
                sun     23
2009 strawberry sat     11
                sun     13
     banana     sat     23
                sun     24

여태까지는 그런대로 잘됐다. 그러나 토요일의 모든 수치가 절반에 불과하다는 점을 생각해 봅시다! 나는 앉은 모든 판매를 2 배로 늘리고 싶다.

이것에 대한 나의 첫번째 시도는 다음과 같다.

sat = d.xs('sat', level='day')
sat = sat * 2
d.update(sat)

그러나 변수 sat가 색인의 일일 수준을 상실했기 때문에 이것은 작동하지 않습니다.

>>> sat
                 sales
year flavour          
2008 strawberry     20
     banana         44
2009 strawberry     22
     banana         46

그래서 팬더는 새로운 판매 수치를 이전 데이터 프레임에 다시 결합하는 방법을 모릅니다.

나는 빠른 찔렀다 :

>>> sat = d.xs('sat', level='day', copy=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 2248, in xs
    raise ValueError('Cannot retrieve view (copy=False)')
ValueError: Cannot retrieve view (copy=False)

나는 그 실수가 무엇인지 전혀 몰랐다. 그러나 나는 산을 두더지에서 만들고있는 것처럼 느낀다. 누구든지이 일을 할 올바른 방법을 알고 있습니까?

미리 감사드립니다. 롭

해결법

  1. ==============================

    1.참고 : 곧 출시 될 0.13의 drop_level 인수가 xs에 추가되었습니다 (이 질문으로 인해!) :

    참고 : 곧 출시 될 0.13의 drop_level 인수가 xs에 추가되었습니다 (이 질문으로 인해!) :

    In [42]: df.xs('sat', level='day', drop_level=False)
    Out[42]:
                         sales
    year flavour    day
    2008 strawberry sat     10
    

    또 다른 옵션은 select (동일한 데이터의 하위 DataFrame (사본)을 추출합니다. 즉, 색인이 동일하므로 올바르게 업데이트 할 수 있음).

    In [11]: d.select(lambda x: x[2] == 'sat') * 2
    Out[11]:
                         sales
    year flavour    day
    2008 strawberry sat     20
         banana     sat     44
    2009 strawberry sat     22
         banana     sat     46
    
    In [12]: d.update(d.select(lambda x: x[2] == 'sat') * 2)
    

    또 다른 옵션은 적용을 사용하는 것입니다.

    In [21]: d.apply(lambda x: x*2 if x.name[2] == 'sat' else x, axis=1)
    

    또 다른 옵션은 get_level_values를 사용하는 것입니다 (이것이 아마도 가장 효율적인 방법 일 것입니다) :

    In [22]: d[d.index.get_level_values('day') == 'sat'] *= 2
    

    또 다른 옵션은 'day'수준을 열로 올린 다음 적용을 사용하는 것입니다.

  2. ==============================

    2..loc 인덱서를 사용하여 MultiIndex가있는 DataFrame에서 데이터의 하위 집합을 선택할 수 있습니다. 원래 질문의 데이터가 있다고 가정합니다.

    .loc 인덱서를 사용하여 MultiIndex가있는 DataFrame에서 데이터의 하위 집합을 선택할 수 있습니다. 원래 질문의 데이터가 있다고 가정합니다.

                         sales
    year flavour    day       
    2008 strawberry sat     10
                    sun     12
         banana     sat     22
                    sun     23
    2009 strawberry sat     11
                    sun     13
         banana     sat     23
                    sun     24
    

    이 DataFrame은 인덱스에 3 개의 레벨을 가지며 각 레벨에는 이름 (연도, 풍미 및 일)이 있습니다. 또한 레벨은 암시 적으로 외부에서 0으로 시작하는 정수 위치에 제공됩니다. 따라서 올해의 레벨은 0, 1의 풍미, 2의 날짜로 참조 될 수 있습니다.

    레벨 0은 선택할 수있는 가장 쉬운 레벨입니다. 예를 들어, 2008 년을 선택하려면 다음을 수행 할 수 있습니다.

    df.loc[2008]
    
                    sales
    flavour    day       
    strawberry sat     10
               sun     12
    banana     sat     22
               sun     23
    

    그러면 외부 인덱스 수준이 삭제됩니다. 외부 레벨을 유지하려면 선택 사항을 목록 (또는 슬라이스)으로 전달할 수 있습니다.

    df.loc[[2008]]  # df.loc[2008:2008] gets the same result
    
                         sales
    year flavour    day       
    2008 strawberry sat     10
                    sun     12
         banana     sat     22
                    sun     23
    

    레벨 0이 아닌 다른 레벨에서 선택하는 것은 더 복잡합니다. 2008 년, 바나나, 토 같은 특정 조합을 선택하여 시작하겠습니다. 이렇게하려면 조합을 .loc에 튜플로 전달합니다.

    df.loc[(2008, 'banana', 'sat')]
    
    sales    22
    Name: (2008, banana, sat), dtype: int64
    

    나는 항상 위와 같은 괄호를 사용하지만 파이썬은 쉼표로 구분 된 값 집합을 튜플로 자동 해석하므로 다음과 같은 결과가 나타납니다.

    df.loc[2008, 'banana', 'sat']
    

    모든 레벨이 떨어지고 시리즈가 반환되었습니다. 목록 안에 튜플을 전달하여 레벨을 유지할 수 있습니다.

    df.loc[[(2008, 'banana', 'sat')]]
    
                      sales
    year flavour day       
    2008 banana  sat     22
    

    앞의 예제는 각 레벨에서 하나의 선택을했습니다. 목록을 사용하여 원하는 수준의 모든 값을 포함 할 수 있습니다. 예를 들어 바나나 맛과 토요일과 일요일에 2008 년과 2009 년의 모든 행을 선택하려면 다음을 수행 할 수 있습니다.

    df.loc[([2008, 2009], 'banana', ('sat','sun'))]
    
                      sales
    year flavour day       
    2008 banana  sat     22
                 sun     23
    2009 banana  sat     23
                 sun     24
    

    다시 말하지만, 튜플을 나타 내기 위해 괄호 안에 전체 선택 사항을 래핑 할 필요는 없으며 간단히 할 수 있습니다.

    df.loc[[2008, 2009], 'banana', ('sat','sun')]
    

    대신에 특정 레벨의 모든 값을 선택하려고 할 수 있습니다. 예를 들어, 모든 년, 모든 풍미 및 단지 토요일을 선택하려고합시다. 다음과 같이 작동한다고 생각할 수 있습니다.

    df.loc[:, :, 'sat']
    

    그러나 이것은 '너무 많은 인덱서의 IndexError를 만나게됩니다. 특정 레벨에서 모든 값을 선택하는 세 가지 다른 방법이 있습니다.

    세 가지 모두 다음과 같습니다.

                         sales
    year flavour    day       
    2008 strawberry sat     10
         banana     sat     22
    2009 strawberry sat     11
         banana     sat     23
    
  3. from https://stackoverflow.com/questions/17552997/how-to-update-a-subset-of-a-multiindexed-pandas-dataframe by cc-by-sa and MIT license