Pandalar birleştirmeyi kullanırken dizin nasıl korunur?


126

İkisini birleştirmek istiyorum DataFrames ve ilk çerçevedeki dizini birleştirilmiş veri kümesindeki dizin olarak tutmak . Ancak, birleştirmeyi yaptığımda, sonuçta elde edilen DataFrame tamsayı indeksine sahip. İndeksi sol veri çerçevesinden korumak istediğimi nasıl belirtebilirim?

In [4]: a = pd.DataFrame({'col1': {'a': 1, 'b': 2, 'c': 3}, 
                          'to_merge_on': {'a': 1, 'b': 3, 'c': 4}})

In [5]: b = pd.DataFrame({'col2': {0: 1, 1: 2, 2: 3}, 
                          'to_merge_on': {0: 1, 1: 3, 2: 5}})

In [6]: a
Out[6]:
   col1  to_merge_on
a     1            1
b     2            3
c     3            4

In [7]: b
Out[7]:
   col2  to_merge_on
0     1            1
1     2            3
2     3            5

In [8]: a.merge(b, how='left')
Out[8]:
   col1  to_merge_on  col2
0     1            1   1.0
1     2            3   2.0
2     3            4   NaN

In [9]: _.index
Out[9]: Int64Index([0, 1, 2], dtype='int64')

DÜZENLEME: Kolayca yeniden üretilebilen örnek koda geçildi


2
Belirli bir sütunda birleştirirseniz, hangi endekslerin kullanılacağı net değildir (her ikisinin de farklı olması durumunda).
bonobo

Yanıtlar:


162
In [5]: a.reset_index().merge(b, how="left").set_index('index')
Out[5]:
       col1  to_merge_on  col2
index
a         1            1     1
b         2            3     2
c         3            4   NaN

Not: Bazı sol birleştirme işlemleri için, ave arasında birden fazla eşleşme varsa daha fazla satırla sonuçlanabilir bve tekilleştirmeniz gerekir ( tekilleştirme için belgeler ). Bu yüzden pandalar dizini sizin için tutmuyor.


4
Çok zeki. a.merge (b, nasıl = "sol"). set_index (a.index) de çalışır, ancak daha az sağlam görünür (çünkü ilk bölümü, indeks değerlerini sıfırlamadan önce a'ya kaybeder.)
DanB

11
Bu özel durum için bunlar eşdeğerdir. Ancak birçok birleştirme işlemi için ortaya çıkan çerçeve, orijinal açerçeveyle aynı sayıda satıra sahip değildir . reset_index, dizini normal bir sütuna taşır ve bu sütundan set_index, birleştirme işlemi nedeniyle a'nın satırları çoğaltıldığında / kaldırıldığında da ilgilenir.
Wouter Overmeire

1
@Wouter Sol bir birleştirmenin varsayılan olarak neden yeniden dizin oluşturacağını bilmek isterim. Daha fazlasını nereden öğrenebilirim?
Matthew

7
Güzel! Kullandığım dizin adını açıkça belirtmekten kaçınmak için a.reset_index().merge(b, how="left").set_index(a.index.names).
Truls

3
Pandalar kötü bir şekilde API'nin tekrar saldıracağını düşündü.
Henry Henrinson

7

Sol dataframe üzerinde indeksin bir kopyasını oluşturabilir ve birleştirme yapabilirsiniz.

a['copy_index'] = a.index
a.merge(b, how='left')

Bu basit yöntemi, büyük veri çerçevesiyle çalışırken ve pd.merge_asof()(veyadd.merge_asof() ) .

Bu yaklaşım, indeksi sıfırlamak pahalı olduğunda (büyük veri çerçevesi) daha üstün olacaktır.


1
Bu en iyi cevap. Birleştirme sırasında eski dizinlerinizi korumak istemenizin birçok nedeni vardır (ve kabul edilen yanıt dizinleri korumaz, yalnızca onları sıfırlar). 2'den fazla veri çerçevesini birleştirmeye çalışırken yardımcı olur, vb ...
Marses

2
(Orijinal) dizin adını koruduğu için üstün çözüm
Martien Lubberink

olumlu oy verildi, ancak bir uyarıya karşı dikkatli olun, çoklu dizin kullanırken, endeksleriniz [copy_index] adlı tek bir sütunda bir demet olarak saklanacaktır
geekidharsh

6

Pd.merge olmayan bir çözüm var. kullanılması mapveset_index

In [1744]: a.assign(col2=a['to_merge_on'].map(b.set_index('to_merge_on')['col2']))
Out[1744]:
   col1  to_merge_on  col2
a     1            1   1.0
b     2            3   2.0
c     3            4   NaN

Ve indexdizin için sahte bir isim vermez .


1
Çoklu dizinler gibi uç durumlarda muhtemelen daha iyi çalışacağından, bu kabul edilen yanıttan daha üstün görünüyor. Bu konuda yorum yapan var mı?
BallpointBen

1
soru, ya birden çok sütun atamanız gerekirse, bu yaklaşım işe yarar mı yoksa yalnızca 1 alanla mı sınırlı?
Yuca

@Yuca: Bu muhtemelen birden çok sütunla çalışmayacaktır, çünkü birden çok sütunu alt kümeye koyduğunuzda, pd.Dataframebir pd.Series. .map()Yöntem, yalnızca tanımlanır pd.Series. Bu şu anlama gelir: a[['to_merge_on_1', 'to_merge_on_2']].map(...)işe yaramaz.
Dataman

4
df1 = df1.merge(
        df2, how="inner", left_index=True, right_index=True
    )

Bu, df1 indeksinin korunmasına izin verir


Bu iş gibi görünüyor, ama ben bunu kullandığınızda on=list_of_cols], bu belgelere çelişmektedir: If joining columns on columns, the DataFrame indexes *will be ignored*. Sütunlara karşı indeks kullanmaktan birinin önceliği var mı?
Itamar Katz

0

Sanırım farklı bir çözüm buldum. Sol tablonun indeksine dayalı bir sütun değeri üzerinde indeks değerinde sol tabloya ve sağ tabloya katılıyordum. Yaptığım şey normal bir birleşmeydi:

First10ReviewsJoined = pd.merge(First10Reviews, df, left_index=True, right_on='Line Number')

Sonra birleştirilmiş tablodan yeni dizin numaralarını aldım ve Duygu Satırı Numarası adlı yeni bir sütuna koydum:

First10ReviewsJoined['Sentiment Line Number']= First10ReviewsJoined.index.tolist()

Ardından dizini, Satır Numarası (sol tablo dizininden katıldığım sütun değeri) olarak adlandırılan önceden var olan sütuna göre orijinal, sol tablo dizinine manuel olarak ayarladım:

First10ReviewsJoined.set_index('Line Number', inplace=True)

Ardından, boş kalması için Satır Numarasının dizin adını kaldırın:

First10ReviewsJoined.index.name = None

Belki biraz hack ama iyi ve nispeten basit çalışıyor gibi görünüyor. Ayrıca, verilerinizin kopyalanması / karıştırılması riskini azalttığını tahmin edin. Umarım hepsi mantıklıdır.


0

başka bir basit seçenek, dizini daha önce olduğu gibi yeniden adlandırmaktır:

a.merge(b, how="left").set_axis(a.index)

birleştirme, veri çerçevesi 'a'daki sırayı korur, ancak dizini sıfırlar, böylece set_axis kullanmak için kaydedilir

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.