Bu soruyu kendim için cevaplama sürecinde çok şey öğrendim ve bir örnek kataloğu ve bazı açıklamalar hazırlamak istedim.
levelsTartışmanın noktasına özel cevap sona doğru gelecektir.
pandas.concat: Eksik Kılavuz
Mevcut Belgelere Bağlantı
Nesneleri içe aktarır ve tanımlar
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), index=[2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), index=[1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), index=[1, 3])
s1 = pd.Series([1, 2], index=[2, 3])
s2 = pd.Series([3, 4], index=[1, 2])
s3 = pd.Series([5, 6], index=[1, 3])
Argümanlar
objs
Karşılaştığımız ilk argüman şudur objs:
objs : Series, DataFrame veya Panel nesnelerinin dizisi veya eşlemesi Bir dikte iletilirse, sıralanan anahtarlar, iletilmediği sürece anahtarlar bağımsız değişkeni olarak kullanılır ve bu durumda değerler seçilir (aşağıya bakın). Hiçbiri nesnesi, tümü Yok olmadıkça sessizce bırakılır; bu durumda bir Değer Hatası ortaya çıkar
- Genellikle bunun bir
Seriesveya DataFramenesneler listesi ile kullanıldığını görüyoruz .
- Bunun
dictda çok faydalı olabileceğini göstereceğim .
- Jeneratörler de kullanılabilir ve olduğu gibi kullanıldığında yararlı olabilir
map.map(f, list_of_df)
Şimdilik, yukarıda tanımlanan DataFrameve Seriesnesnelerin bazılarının bir listesine bağlı kalacağız . Çok yararlı MultiIndexsonuçlar vermek için sözlüklerden nasıl yararlanılabileceğini daha sonra göstereceğim .
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
axis
Karşılaştığımız ikinci argüman axis, varsayılan değeri şudur 0:
eksen : {0 / 'dizin', 1 / 'sütunlar'}, varsayılan 0 Birlikte birleştirilecek eksen.
İki DataFrames ile axis=0(istiflenmiş)
Değerleri için 0veya indexşunu demek istiyoruz: "Sütunlar boyunca hizalayın ve dizine ekleyin".
Yukarıda gösterildiği gibi axis=0, çünkü 0varsayılan değerdir ve değerin örtüşmesine rağmen d2indeksinin indeksini genişlettiğini görüyoruz :d12
pd.concat([d1, d2], axis=0)
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
İki DataFrames ile axis=1(yan yana)
Değerler için 1veya columnsşunu demek istiyoruz: "Dizin boyunca hizalayın ve sütunlara ekleyin",
pd.concat([d1, d2], axis=1)
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
Ortaya çıkan endeks endekslerinin birliktir ve elde edilen kolonlar gelen sütunların uzantısı olduğunu görebiliyoruz d1sütunları ile d2.
İki (veya Üç) Seriesile axis=0(istiflenmiş)
Birleştirilirken pandas.Seriesbirlikte axis=0, biz geri almak pandas.Series. Ortaya çıkanların adı, birleştirilenlerin tümü aynı ada sahip olmadıkça Seriesolacaktır . Dikkat edin biz sonuçlanımını yazdırmak . Mevcut olmadığında, adın olduğunu varsayabiliriz .NoneSeries'Name: A'SeriesSeriesNone
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('A'),
pd.concat( | [s1.rename('A'), | [s1.rename('A'), | s2.rename('B'),
[s1, s2]) | s2]) | s2.rename('A')]) | s3.rename('A')])
-------------- | --------------------- | ---------------------- | ----------------------
2 1 | 2 1 | 2 1 | 2 1
3 2 | 3 2 | 3 2 | 3 2
1 3 | 1 3 | 1 3 | 1 3
2 4 | 2 4 | 2 4 | 2 4
dtype: int64 | dtype: int64 | Name: A, dtype: int64 | 1 5
| | | 3 6
| | | dtype: int64
İki (veya Üç) Seriesile axis=1(yan yana)
Birleştirirken pandas.Seriesbirlikte axis=1, bunun namebiz elde edilen bir sütun adı anlaması için bakınız bu özellik pandas.DataFrame.
| | pd.concat(
| pd.concat( | [s1.rename('X'),
pd.concat( | [s1.rename('X'), | s2.rename('Y'),
[s1, s2], axis=1) | s2], axis=1) | s3.rename('Z')], axis=1)
---------------------- | --------------------- | ------------------------------
0 1 | X 0 | X Y Z
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 5.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 NaN
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN 6.0
Karışık Seriesve DataFrameile axis=0(yığın)
Bir Seriesve DataFrameboyunca birleştirme gerçekleştirirken axis=0, hepsini Seriestek sütun DataFrames'ye dönüştürürüz .
Bunun bir bitiştirme olduğuna özellikle dikkat edin axis=0; bu, sütunları hizalarken dizini (satırları) genişletmek anlamına gelir. Aşağıdaki örneklerde [2, 3, 2, 3], endekslerin gelişigüzel eklenmesi olan endeksin olduğunu görüyoruz . Bağımsız Seriesdeğişken ile sütunun adlandırılmasını zorlamadıkça sütunlar çakışmaz:to_frame :
pd.concat( |
[s1.to_frame(), d1]) | pd.concat([s1, d1])
------------------------- | ---------------------
0 A B C | 0 A B C
2 1.0 NaN NaN NaN | 2 1.0 NaN NaN NaN
3 2.0 NaN NaN NaN | 3 2.0 NaN NaN NaN
2 NaN 0.1 0.2 0.3 | 2 NaN 0.1 0.2 0.3
3 NaN 0.1 0.2 0.3 | 3 NaN 0.1 0.2 0.3
Sonuçlarını görebilirsiniz pd.concat([s1, d1])to_frame kendimi geliştirmişim gibi aynı olduğunu görebilirsiniz .
Ancak, elde edilen sütunun adını bir parametresi ile kontrol edebilirim to_frame. Yeniden adlandırma Seriesile renameyöntem etmez olup elde edilen sütun adı kontrolDataFrame .
pd.concat( | pd.concat( | pd.concat(
[s1.to_frame('X'), d1]) | [s1.rename('X'), d1]) | [s1.to_frame('B'), d1])
---------------------------- | -------------------------- | ----------------------------
A B C X | 0 A B C | A B C
2 NaN NaN NaN 1.0 | 2 1.0 NaN NaN NaN | 2 NaN 1.0 NaN
3 NaN NaN NaN 2.0 | 3 2.0 NaN NaN NaN | 3 NaN 2.0 NaN
2 0.1 0.2 0.3 NaN | 2 NaN 0.1 0.2 0.3 | 2 0.1 0.2 0.3
3 0.1 0.2 0.3 NaN | 3 NaN 0.1 0.2 0.3 | 3 0.1 0.2 0.3
Karışık Series ve DataFrameile axis=1(yan yana)
Bu oldukça sezgiseldir. Seriessütun adı Series, bir nameöznitelik mevcut olmadığında varsayılan olarak bu tür nesnelerin bir numaralandırmasıdır .
| pd.concat(
pd.concat( | [s1.rename('X'),
[s1, d1], | s2, s3, d1],
axis=1) | axis=1)
------------------- | -------------------------------
0 A B C | X 0 1 A B C
2 1 0.1 0.2 0.3 | 1 NaN 3.0 5.0 NaN NaN NaN
3 2 0.1 0.2 0.3 | 2 1.0 4.0 NaN 0.1 0.2 0.3
| 3 2.0 NaN 6.0 0.1 0.2 0.3
join
Üçüncü argüman, joinortaya çıkan birleştirmenin bir dış birleştirme mi (varsayılan) yoksa bir iç birleştirme mi olması gerektiğini açıklar.
birleşim : {'iç', 'dış'}, varsayılan 'dış'
Diğer eksenlerde dizinler nasıl işlenir.
Görünüşe göre yok leftya da yokrightpd.concat göre, birleştirmek için iki nesneden daha fazlasını işleyebilecek bir seçenek .
Durumunda d1ve d2, seçenekler benziyor:
outer
pd.concat([d1, d2], axis=1, join='outer')
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
inner
pd.concat([d1, d2], axis=1, join='inner')
A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6
join_axes
Dördüncü argüman, leftbirleşmemizi ve daha fazlasını yapmamızı sağlayan şeydir .
join_axes : Index nesnelerinin listesi
İç / dış küme mantığını gerçekleştirmek yerine diğer n - 1 eksenleri için kullanılacak özel indeksler.
Sol Birleştirme
pd.concat([d1, d2, d3], axis=1, join_axes=[d1.index])
A B C B C D A B D
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
Sağ Birleştirme
pd.concat([d1, d2, d3], axis=1, join_axes=[d3.index])
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
ignore_index
ignore_index : boolean, varsayılan False
If True, dizin değerlerini birleştirme ekseni boyunca kullanmayın. Ortaya çıkan eksen 0, ..., n - 1 olarak etiketlenecektir. Bu, birleştirme ekseninin anlamlı indeksleme bilgilerine sahip olmadığı nesneleri birleştiriyorsanız kullanışlıdır. Diğer eksenlerdeki dizin değerlerinin birleşimde hala dikkate alındığına dikkat edin.
d1Üst üste istiflediğimde olduğu gibi d2, indeks değerlerini umursamıyorsam, onları sıfırlayabilir veya görmezden gelebilirim.
| pd.concat( | pd.concat(
| [d1, d2], | [d1, d2]
pd.concat([d1, d2]) | ignore_index=True) | ).reset_index(drop=True)
--------------------- | ----------------------- | -------------------------
A B C D | A B C D | A B C D
2 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6
Ve kullanırken axis=1:
| pd.concat(
| [d1, d2], axis=1,
pd.concat([d1, d2], axis=1) | ignore_index=True)
------------------------------- | -------------------------------
A B C B C D | 0 1 2 3 4 5
1 NaN NaN NaN 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 3 0.1 0.2 0.3 NaN NaN NaN
keys
Karşılık gelen MultiIndex'e tuple veya skaler değerler atamak için bir skaler değerler veya tuple listesi geçirebiliriz. Aktarılan listenin uzunluğu, birleştirilen öğelerin sayısıyla aynı uzunlukta olmalıdır.
anahtarlar : sıra, varsayılan Yok
Birden fazla düzey geçtiyse, tuple içermelidir. En dış düzey olarak iletilen anahtarları kullanarak hiyerarşik dizin oluşturun
axis=0
SeriesNesneleri birleştirirkenaxis=0 (dizini genişletir).
Bu anahtarlar, MultiIndexindex niteliğindeki bir nesnenin yeni bir başlangıç seviyesi haline gelir .
pd.concat([s1, s2, s3], keys=['A', 'B', 'C']) pd.concat([s1, s2], keys=['A', 'B'])
---------------------------------------------- -------------------------------------
A 2 1 A 2 1
3 2 3 2
B 1 3 B 1 3
2 4 2 4
C 1 5 dtype: int64
3 6
dtype: int64
Bununla birlikte, daha keysda derin oluşturmak için argümanda skaler değerlerden daha fazlasını kullanabiliriz MultiIndex. Burada tuplesuzunluk 2'nin başına iki yeni a düzeyini geçiyoruz MultiIndex:
pd.concat(
[s1, s2, s3],
keys=[('A', 'X'), ('A', 'Y'), ('B', 'X')])
-----------------------------------------------
A X 2 1
3 2
Y 1 3
2 4
B X 1 5
3 6
dtype: int64
axis=1
Sütunlar boyunca uzanırken biraz farklıdır. Kullandığımızda axis=0(yukarıya bakın) , mevcut dizine ek keysolarak MultiIndexseviyeler olarak hareket ettik . İçinaxis=1Series nesnelerin sahip olmadığı bir eksene , yani columnsniteliğe atıfta bulunuyoruz.
İkinin Varyasyonları
Series gayrimenkulünü
axis=1
Bildirim adlandırma olduğunu s1ve s2bu kadar uzun diye konularda keysgeçirilir, ancak eğer geçersiz olur keysgeçirilir.
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('U'),
pd.concat( | [s1, s2], | [s1.rename('U'), | s2.rename('V')],
[s1, s2], | axis=1, | s2.rename('V')], | axis=1,
axis=1) | keys=['X', 'Y']) | axis=1) | keys=['X', 'Y'])
-------------- | --------------------- | ---------------------- | ----------------------
0 1 | X Y | U V | X Y
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN
MultiIndexile
Seriesve
axis=1
pd.concat(
[s1, s2],
axis=1,
keys=[('W', 'X'), ('W', 'Y')])
-----------------------------------
W
X Y
1 NaN 3.0
2 1.0 4.0
3 2.0 NaN
İki
DataFrame ile
axis=1
Olduğu gibi axis=0örneklerde, keysbir için seviyeleri eklemek MultiIndex, ama nesneye bu kez saklanan columnsöznitelik.
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=[('First', 'X'), ('Second', 'X')])
------------------------------- | --------------------------------------------
X Y | First Second
A B C B C D | X X
1 NaN NaN NaN 0.4 0.5 0.6 | A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
| 3 0.1 0.2 0.3 NaN NaN NaN
Series ve
DataFrame ile
axis=1
Bu aldatıcıdır. Bu durumda, bir skaler anahtar değeri için sadece endeksin seviyesi olarak hareket edemez Seriesda ilk seviyesi olarak hareket ederken, bir kolon olduğunda nesne MultiIndexiçin DataFrame. Böylece Pandalar , sütun adının kaynağı olarak nesnenin nameözniteliğini tekrar kullanacaktır Series.
pd.concat( | pd.concat(
[s1, d1], | [s1.rename('Z'), d1],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=['X', 'Y'])
--------------------- | --------------------------
X Y | X Y
0 A B C | Z A B C
2 1 0.1 0.2 0.3 | 2 1 0.1 0.2 0.3
3 2 0.1 0.2 0.3 | 3 2 0.1 0.2 0.3
Sınırlamalar
keysve
MultiIndexçıkarım.
Pandalar yalnızca sütun adlarını Seriesadından çıkarıyor gibi görünmektedir , ancak farklı sayıda sütun düzeyine sahip veri çerçeveleri arasında benzer bir birleştirme yaparken boşlukları doldurmayacaktır.
d1_ = pd.concat(
[d1], axis=1,
keys=['One'])
d1_
One
A B C
2 0.1 0.2 0.3
3 0.1 0.2 0.3
Daha sonra, bunu sütun nesnesinde yalnızca bir seviyeye sahip başka bir veri çerçevesiyle birleştirin ve Pandalar, nesnenin demetlerini yapmayı MultiIndexve tüm veri çerçevelerini tek bir nesne, skaler ve demet seviyesi gibi birleştirmeyi reddeder .
pd.concat([d1_, d2], axis=1)
(One, A) (One, B) (One, C) B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
A dictyerine a geçmeklist
Bir pandas.concatsözlüğü iletirken, keysparametre olarak sözlükteki anahtarları kullanacaktır .
pd.concat( | pd.concat(
{0: d1, 1: d2}) | {0: d1, 1: d2}, axis=1)
----------------------- | -------------------------------
A B C D | 0 1
0 2 0.1 0.2 0.3 NaN | A B C B C D
3 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
levels
Bu, keysbağımsız değişkenle bağlantılı olarak kullanılır. levelsVarsayılan değeri olarak bırakıldığında None, Pandalar ortaya çıkan her seviyenin benzersiz değerlerini alacak MultiIndexve bunu sonuçta elde edilen index.levelsöznitelikte kullanılan nesne olarak kullanacaktır .
düzeyler : dizi listesi, varsayılan Yok
Bir MultiIndex oluşturmak için kullanılacak belirli düzeyler (benzersiz değerler). Aksi takdirde anahtarlardan çıkarılacaklardır.
Pandalar bu seviyelerin ne olması gerektiğini zaten anlamışsa, bunu kendimiz belirlemenin ne gibi bir avantajı var? Bir örnek göstereceğim ve bunun neden yararlı olabileceğine dair diğer nedenleri düşünmeyi size bırakacağım.
Misal
Belgelere göre, levelsargüman bir dizi listesidir. Bu pandas.Index, bu dizilerden biri olarak başka birini kullanabileceğimiz anlamına gelir .
Veri çerçevesini düşünün dfbirleşimidir d1, d2ve d3:
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'])
df
First Second Fourth
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
Sütunlar nesnesinin seviyeleri şunlardır:
print(df, *df.columns.levels, sep='\n')
Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')
Kullandığımız Eğer sumbir dahilinde groupbyelde ederiz:
df.groupby(axis=1, level=0).sum()
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
Peki ya ve ['First', 'Second', 'Fourth']adında başka bir eksik kategori varsa ? Ve bunların bir toplama işleminin sonuçlarına dahil edilmesini mi istedim ? Bunu bir . Ve bunu önceden belirtebiliriz.ThirdFifthgroupbypandas.CategoricalIndexlevels argümanla .
Onun yerine şöyle tanımlayalım df:
cats = ['First', 'Second', 'Third', 'Fourth', 'Fifth']
lvl = pd.CategoricalIndex(cats, categories=cats, ordered=True)
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'],
levels=[lvl]
)
df
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
Ancak sütunlar nesnesinin ilk seviyesi:
df.columns.levels[0]
CategoricalIndex(
['First', 'Second', 'Third', 'Fourth', 'Fifth'],
categories=['First', 'Second', 'Third', 'Fourth', 'Fifth'],
ordered=True, dtype='category')
Ve groupbyözetimiz şöyle görünüyor:
df.groupby(axis=1, level=0).sum()
First Second Third Fourth Fifth
1 0.0 1.5 0.0 2.4 0.0
2 0.6 1.5 0.0 0.0 0.0
3 0.6 0.0 0.0 2.4 0.0
names
Bu, sonuçta ortaya çıkan seviyeleri adlandırmak için kullanılır MultiIndex. namesListenin uzunluğu , sonuçtaki düzeylerin sayısıyla eşleşmelidir MultiIndex.
adlar : liste, varsayılan Hiçbiri
Ortaya çıkan hiyerarşik dizindeki düzeyler için adlar
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
keys=[0, 1], | axis=1, keys=[0, 1],
names=['lvl0', 'lvl1']) | names=['lvl0', 'lvl1'])
----------------------------- | ----------------------------------
A B C D | lvl0 0 1
lvl0 lvl1 | lvl1 A B C B C D
0 2 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
2 NaN 0.4 0.5 0.6 |
verify_integrity
Kendinden açıklamalı belgeler
valid_integrity : boolean, varsayılan False
Yeni birleştirilmiş eksenin kopyalar içerip içermediğini kontrol edin. Bu, gerçek veri birleştirme işlemine göre çok pahalı olabilir.
Bitiştirmek kaynaklanan endeksi Çünkü d1ve d2eşsiz değil, doğruluk kontrolü yapmasını engeller.
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
Ve
pd.concat([d1, d2], verify_integrity=True)
> ValueError: Dizinler çakışan değerlere sahiptir: [2]