Bu soruyu kendim için cevaplama sürecinde çok şey öğrendim ve bir örnek kataloğu ve bazı açıklamalar hazırlamak istedim.
levels
Tartış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
Series
veya DataFrame
nesneler listesi ile kullanıldığını görüyoruz .
- Bunun
dict
da ç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 DataFrame
ve Series
nesnelerin bazılarının bir listesine bağlı kalacağız . Çok yararlı MultiIndex
sonuç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 DataFrame
s ile axis=0
(istiflenmiş)
Değerleri için 0
veya index
şunu demek istiyoruz: "Sütunlar boyunca hizalayın ve dizine ekleyin".
Yukarıda gösterildiği gibi axis=0
, çünkü 0
varsayılan değerdir ve değerin örtüşmesine rağmen d2
indeksinin indeksini genişlettiğini görüyoruz :d1
2
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 DataFrame
s ile axis=1
(yan yana)
Değerler için 1
veya 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 d1
sütunları ile d2
.
İki (veya Üç) Series
ile axis=0
(istiflenmiş)
Birleştirilirken pandas.Series
birlikte axis=0
, biz geri almak pandas.Series
. Ortaya çıkanların adı, birleştirilenlerin tümü aynı ada sahip olmadıkça Series
olacaktır . Dikkat edin biz sonuçlanımını yazdırmak . Mevcut olmadığında, adın olduğunu varsayabiliriz .None
Series
'Name: A'
Series
Series
None
| | | 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 Üç) Series
ile axis=1
(yan yana)
Birleştirirken pandas.Series
birlikte axis=1
, bunun name
biz 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 Series
ve DataFrame
ile axis=0
(yığın)
Bir Series
ve DataFrame
boyunca birleştirme gerçekleştirirken axis=0
, hepsini Series
tek sütun DataFrame
s'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 Series
değ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 Series
ile rename
yö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 DataFrame
ile axis=1
(yan yana)
Bu oldukça sezgiseldir. Series
sü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, join
ortaya çı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 left
ya da yokright
pd.concat
göre, birleştirmek için iki nesneden daha fazlasını işleyebilecek bir seçenek .
Durumunda d1
ve 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, left
birleş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
Series
Nesneleri birleştirirkenaxis=0
(dizini genişletir).
Bu anahtarlar, MultiIndex
index 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 keys
da derin oluşturmak için argümanda skaler değerlerden daha fazlasını kullanabiliriz MultiIndex
. Burada tuples
uzunluk 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 keys
olarak MultiIndex
seviyeler olarak hareket ettik . İçinaxis=1
Series
nesnelerin sahip olmadığı bir eksene , yani columns
niteliğe atıfta bulunuyoruz.
İkinin Varyasyonları
Series
gayrimenkulünü
axis=1
Bildirim adlandırma olduğunu s1
ve s2
bu kadar uzun diye konularda keys
geçirilir, ancak eğer geçersiz olur keys
geç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
MultiIndex
ile
Series
ve
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, keys
bir 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 Series
da ilk seviyesi olarak hareket ederken, bir kolon olduğunda nesne MultiIndex
iç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
keys
ve
MultiIndex
çıkarım.
Pandalar yalnızca sütun adlarını Series
adı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ı MultiIndex
ve 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 dict
yerine a geçmeklist
Bir pandas.concat
sözlüğü iletirken, keys
parametre 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, keys
bağımsız değişkenle bağlantılı olarak kullanılır. levels
Varsayılan değeri olarak bırakıldığında None
, Pandalar ortaya çıkan her seviyenin benzersiz değerlerini alacak MultiIndex
ve 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, levels
argü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 df
birleşimidir d1
, d2
ve 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 sum
bir dahilinde groupby
elde 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.Third
Fifth
groupby
pandas.CategoricalIndex
levels
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
. names
Listenin 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ü d1
ve d2
eş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]