Pandalar: Çok düzeyli bir sütun dizininden seviye düşürülüyor mu?


242

Çok düzeyli bir sütun dizinim varsa:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> pd.DataFrame([[1,2], [3,4]], columns=cols)
    bir
   --- + -
    b | c
- + --- + -
0 | 1 | 2
1 | 3 | 4

Bu dizinin "a" seviyesini nasıl düşürebilirim, bu yüzden şu şekilde bitiririm:

    b | c
- + --- + -
0 | 1 | 2
1 | 3 | 4

3
Hem dizin hem de sütunlar için bunu yapan bir DataFrame yöntemine sahip olmak güzel olurdu. Dizin düzeylerini düşürme veya seçme.
Sören

@ Sören stackoverflow.com/a/56080234/3198568 adresine bakın . droplevelişleri çok düzeyli dizinlerde veya sütunlarda parametre aracılığıyla çalışabilir axis.
irene

Yanıtlar:


306

Şunları kullanabilirsiniz MultiIndex.droplevel:

>>> cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
>>> df = pd.DataFrame([[1,2], [3,4]], columns=cols)
>>> df
   a   
   b  c
0  1  2
1  3  4

[2 rows x 2 columns]
>>> df.columns = df.columns.droplevel()
>>> df
   b  c
0  1  2
1  3  4

[2 rows x 2 columns]

55
Hangi seviyenin düştüğünü açıkça söylemek en iyisidir. Seviyeler üstten başlayarak 0 dizinlidir. >>> df.columns = df.columns.droplevel(0)
Ted Petrou

6
Bırakmaya çalıştığınız dizin üst (sütun) tarafında değil, sol (satır) tarafındaysa, "sütunları" "dizin" olarak değiştirebilir ve aynı yöntemi kullanabilirsiniz:>>> df.index = df.index.droplevel(1)
Idodo

7
Panda 0.23.4 sürümünde df.columns.droplevel()artık mevcut değil.
yoonghm

8
@yoonghm Orada, muhtemelen sadece çok dizinli olmayan sütunlarda çağırıyorsunuz
matt harrison

1
Üç seviye derinim vardı ve sadece orta seviyeye düşmek istedim. En düşük (seviye [2]) ve sonra en yüksek (seviye [0]) düşürmenin en iyi sonucu verdiğini buldum. >>>df.columns = df.columns.droplevel(2) >>>df.columns = df.columns.droplevel(0)
Kyle C

65

Dizini bırakmanın başka bir yolu da bir liste kavraması kullanmaktır:

df.columns = [col[1] for col in df.columns]

   b  c
0  1  2
1  3  4

Bu strateji, alt düzey iki 'y' içeren aşağıdaki örnekte olduğu gibi her iki düzeydeki adları birleştirmek istiyorsanız da yararlıdır:

cols = pd.MultiIndex.from_tuples([("A", "x"), ("A", "y"), ("B", "y")])
df = pd.DataFrame([[1,2, 8 ], [3,4, 9]], columns=cols)

   A     B
   x  y  y
0  1  2  8
1  3  4  9

Üst seviyeyi düşürmek, 'y' diziniyle iki sütun bırakacaktır. Bu, isimleri liste kavrayışı ile birleştirerek önlenebilir.

df.columns = ['_'.join(col) for col in df.columns]

    A_x A_y B_y
0   1   2   8
1   3   4   9

Bu bir groupby yaptıktan sonra yaşadığım bir sorun ve onu çözen diğer soruyu bulmak biraz zaman aldı . Bu çözümü burada özel duruma uyarladım.


2
[col[1] for col in df.columns]daha doğrudan df.columns.get_level_values(1).
Eric O Lebigot

2
Benzer bir ihtiyaç vardı, burada bazı sütunlar boş seviye değerlerine sahipti. Aşağıdakileri kullandı:[col[0] if col[1] == '' else col[1] for col in df.columns]
Logan

43

Bunu yapmanın başka bir yolu , .xs yöntemini kullanarak dfbir kesitine göre yeniden atamaktır .df

>>> df

    a
    b   c
0   1   2
1   3   4

>>> df = df.xs('a', axis=1, drop_level=True)

    # 'a' : key on which to get cross section
    # axis=1 : get cross section of column
    # drop_level=True : returns cross section without the multilevel index

>>> df

    b   c
0   1   2
1   3   4

1
Bu yalnızca tüm sütun düzeyi için tek bir etiket olduğunda çalışır.
Ted Petrou

1
İkinci seviyeyi düşürmek istediğinizde çalışmaz.
Sören

Aynı seviyede dilimlemek ve bırakmak istiyorsanız bu güzel bir çözümdür. İkinci seviyede dilimlemek istiyorsanız (diyelim b) o seviyeyi bırakın ve ilk seviyeyle ( a) df = df.xs('b', axis=1, level=1, drop_level=True)
Tiffany G. Wilson

27

Pandalar itibariyle 0.24.0 , şimdi kullanabilirsiniz DataFrame.droplevel () :

cols = pd.MultiIndex.from_tuples([("a", "b"), ("a", "c")])
df = pd.DataFrame([[1,2], [3,4]], columns=cols)

df.droplevel(0, axis=1) 

#   b  c
#0  1  2
#1  3  4

Bu, DataFrame yöntem zincirinin yuvarlanmasını sağlamak istiyorsanız çok kullanışlıdır.


Bu, "yerinde" değiştirilmek yerine yeni bir DataFrame döndürülmesinin "en saf" çözümdür.
EliadL

16

Bunu sütunları yeniden adlandırarak da başarabilirsiniz:

df.columns = ['a', 'b']

Bu manuel bir adım içerir, ancak özellikle veri çerçevenizi eninde sonunda yeniden adlandırırsanız bir seçenek olabilir.


Esasen Mint'in ilk cevabı budur. Şimdi, size verildiği gibi, ad listesini (genellikle sıkıcıdır) belirtmeye de gerek yoktur df.columns.get_level_values(1).
Eric O Lebigot

13

sum Level = 1 ile küçük bir numara (level = 1 tamamen benzersiz olduğunda çalış)

df.sum(level=1,axis=1)
Out[202]: 
   b  c
0  1  2
1  3  4

Daha yaygın çözüm get_level_values

df.columns=df.columns.get_level_values(1)
df
Out[206]: 
   b  c
0  1  2
1  3  4

4

Droplevel () işlevimin neden çalışmadığını bilmediğim için bu sorunla mücadele ettim. Birkaçını gözden geçirin ve tablonuzdaki 'a' nın sütun adı ve 'b', 'c' nin dizin olduğunu öğrenin. Bu yardımcı olur mu

df.columns.name = None
df.reset_index() #make index become label

1
Bu istenen çıktıyı hiç üretmez.
Eric O Lebigot

Bu yayınlandığı tarihe göre, düşme seviyesi
Panda
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.