İloc, ix ve loc arasındaki farklar nelerdir?


636

Birisi bu üç dilimleme yönteminin nasıl farklı olduğunu açıklayabilir mi? Dokümanları
gördüm ve bu cevapları gördüm , ama yine de kendimin üçünün nasıl farklı olduğunu açıklayamıyorum. Bana göre, büyük ölçüde değiştirilebilir görünüyorlar, çünkü daha düşük dilimleme seviyelerinde.

Örneğin, a'nın ilk beş satırını almak istediğimizi varsayalım DataFrame. Bunların üçü nasıl çalışıyor?

df.loc[:5]
df.ix[:5]
df.iloc[:5]

Birisi, kullanımlardaki ayrımın daha net olduğu üç vaka sunabilir mi?


7
SettingWithCopyUyarı senaryolarından bahsetmek çok önemlidir: stackoverflow.com/questions/20625582/… ve stackoverflow.com/questions/23688307/…
Paul

Yanıtlar:


970

Not: pandalar sürümü 0.20.0 ve üzeri, ixbir kullanımdan kaldırılmış ve kullanımı locve ilocbunun yerine teşvik edilmektedir. Bu cevabın ixpandaların önceki sürümlerinin kullanıcıları için sağlam bir referans olarak tanımlanmış kısımlarını bıraktım . Aşağıda alternatifleri gösteren örnekler eklenmiştir ix .


İlk olarak, bu üç yöntemin bir özeti:

  • locdizinden belirli etiketler içeren satırları (veya sütunları) alır .
  • ilocdizindeki belirli konumlarda satırlar (veya sütunlar) alır (bu nedenle yalnızca tamsayılar alır).
  • ixgenellikle gibi davranmaya çalışır locancak ilocdizinde bir etiket bulunmuyormuş gibi davranmaya geri döner .

ixKullanımı biraz zorlaştırabilecek bazı incelikleri not etmek önemlidir :

  • dizin tamsayı türündeyse, ixyalnızca etiket tabanlı dizin oluşturmayı kullanır ve konum tabanlı dizine eklemez. Etiket dizinde değilse, bir hata oluşur.

  • dizin yalnızca tamsayı içermiyorsa , o zaman bir tamsayı verilirse, ixhemen etiket tabanlı indeksleme yerine konum tabanlı indeksleme kullanır. Ancak ixbaşka bir tür (ör. Bir dize) verilirse, etiket tabanlı dizine ekleme özelliğini kullanabilir.


Üç yöntem arasındaki farkları göstermek için aşağıdaki Serileri göz önünde bulundurun:

>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN

Tam sayı değeri ile dilimlemeye bakacağız 3.

Bu durumda, s.iloc[:3]bize ilk 3 satırı döndürür (3'ü konum olarak kabul ettiğinden) ve s.loc[:3]bize ilk 8 satırı döndürür (3'ü etiket olarak kabul ettiğinden):

>>> s.iloc[:3] # slice the first three rows
49   NaN
48   NaN
47   NaN

>>> s.loc[:3] # slice up to and including label 3
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

Not , konum üzerinde çalışmak yerine ilk olarak etiketi aradığı için s.ix[:3]aynı Seriyi döndürür s.loc[:3](ve dizini stamsayı türündedir).

Dizinde olmayan bir tamsayı etiketiyle denersek ne olur (diyelim 6)?

Burada s.iloc[:6], Serinin ilk 6 satırını beklendiği gibi döndürür. Ancak, dizinde olmadığı için s.loc[:6]bir KeyError yükseltir 6.

>>> s.iloc[:6]
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN

>>> s.loc[:6]
KeyError: 6

>>> s.ix[:6]
KeyError: 6

Yukarıda belirtilen inceliklere göre, s.ix[:6]şimdi bir KeyError yükseltir, çünkü böyle çalışmaya çalışır, locancak 6dizinde bir bulamaz . Bizim dizin tamsayı türü ixolduğu için gibi davranmaya geri düşmez iloc.

Bununla birlikte, bir tamsayı bir KeyError yükseltmek yerine hemen ixdavranırsa , dizinimiz karışık türde ise iloc:

>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
1   NaN

Unutmayın ixhala gibi tamsayı olmayan ve davranmaya kabul edebilir loc:

>>> s2.ix[:'c'] # behaves like loc given non-integer
a   NaN
b   NaN
c   NaN

Genel tavsiye olarak, yalnızca etiketleri kullanarak dizin oluşturuyorsanız veya yalnızca tamsayı konumlarını kullanarak dizin oluşturuyorsanız, beklenmedik sonuçlardan kaçınmak için locveya ilocile devam edin - kullanmamaya çalışın ix.


Konum tabanlı ve etiket tabanlı indekslemeyi birleştirme

Bazen bir DataFrame verildiğinde, satırlar ve sütunlar için etiket ve konum indeksleme yöntemlerini karıştırmak istersiniz.

Örneğin, aşağıdaki DataFrame'i düşünün. Nasıl iyi satırları yukarı 'c' ve dahil dilim ve ilk dört sütun almak?

>>> df = pd.DataFrame(np.nan, 
                      index=list('abcde'),
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN

Pandaların önceki sürümlerinde (0.20.0'dan önce) ixbunu oldukça düzgün bir şekilde yapmanıza izin verir - satırları etikete ve sütunları konuma göre dilimleyebiliriz (sütunlar için ixvarsayılan olarak konum tabanlı dilimlemenin 4bir sütun adı olmadığına dikkat edin) ):

>>> df.ix[:'c', :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

Pandaların sonraki sürümlerinde, bu sonucu ilocve başka bir yöntemin yardımıyla elde edebiliriz :

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

get_loc()"etiketin bu dizindeki konumunu al" anlamına gelen bir dizin yöntemidir. İle dilimleme ilocbitiş noktası dışında olduğundan, 'c' satırını da istiyorsak bu değere 1 eklememiz gerektiğini unutmayın.

Pandaların belgelerinde burada daha fazla örnek var .


12
Harika bir açıklama! Her zaman yaşadığım ilgili bir soru, eğer varsa, loc, iloc ve ix SettingWithCopy uyarıları ile ne ilişki var? Orada bazı belgeler olduğunu ama dürüst olmak gerekirse ben biraz karıştı hâlâ pandas.pydata.org/pandas-docs/stable/...
measureallthethings

3
@measureallthethings: loc, ilocve ixbirlikte zincirleme takdirde kudreti yine uyarı tetiklemez. Bağlantılı dokümanlarda örnek DataFrame kullanımı, dfmi.loc[:, 'one'].loc[:, 'second']tıpkı dfmi['one']['second']ilk dizin oluşturma işlemi tarafından verilerin bir kopyası (görünümden ziyade) döndürülebileceği için uyarıyı tetikler .
Alex Riley

DateIndex'i bir Date ile veya benzeri bir şeyle aramak istiyorsanız ne kullanırsınız df.ix[date, 'Cash']?
cjm2671

@ cjm2671: her ikisi de locveya ixbu durumda çalışmalıdır. Örneğin, df.loc['2016-04-29', 'Cash']belirli bir tarihe sahip tüm satır dizinlerini "Nakit" sütunundan döndürür. (Dizelerle dizinleri alırken istediğiniz kadar spesifik olabilirsiniz, örneğin '2016-01'Ocak 2016'da düşen tüm tarihleri ​​seçecektir, `` 2016-01-02 11 '' 2 Ocak 2016'da saat 11 ile tarih seçecektir: ??: ?? .)
Alex Riley

Bu yanıtı bir noktada güncellemek istiyorsanız, burada ix github.com/pandas-dev/pandas/issues/14218
JohnE

142

iloctamsayı konumlandırmasına göre çalışır. Satır etiketleriniz ne olursa olsun, her zaman, örneğin ilk satırı yaparak

df.iloc[0]

veya son beş satırı yaparak

df.iloc[-5:]

Sütunlarda da kullanabilirsiniz. Bu, 3. sütunu alır:

df.iloc[:, 2]    # the : in the first position indicates all rows

Satır ve sütunların kesişme noktalarını elde etmek için bunları birleştirebilirsiniz:

df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)

Öte yandan, .locadlandırılmış dizinler kullanın. Dizeleri satır ve sütun etiketleri olarak içeren bir veri çerçevesi oluşturalım:

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])

Sonra ilk satırı alabiliriz

df.loc['a']     # equivalent to df.iloc[0]

ve 'date'sütunun ikinci iki satırı

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]

ve bunun gibi. Şimdi, bir varsayılan satır ve sütun indeksleri işaret değer demektir DataFrametamsayılar 0'dan ve bu durumda olan ilocve locaynı şekilde çalışmaya devam eder. Bu yüzden üç örneğiniz eşdeğerdir. Dizeler veya tarihler gibi sayısal olmayan bir dizininiz varsa, df.loc[:5] hata oluşur.

Ayrıca, yalnızca veri çerçevelerini kullanarak sütun alma işlemini yapabilirsiniz __getitem__:

df['time']    # equivalent to df.loc[:, 'time']

Şimdi konum ve adlandırılmış dizin oluşturmayı karıştırmak istediğinizi varsayalım, yani satırlardaki adları ve sütunlardaki konumları kullanarak dizinleme (açıklığa kavuşturmak için, satır dizininde dizeler ve tamsayılar içeren bir veri çerçevesi oluşturmak yerine veri çerçevemizden seçim yapmak istiyorum sütun dizini). İşte burada .ix:

df.ix[:2, 'time']    # the first two rows of the 'time' column

Boole vektörlerini de locyönteme aktarabileceğinizi de belirtmek gerekir . Örneğin:

 b = [True, False, True]
 df.loc[b] 

1. ve 3. satırlarını döndürür df. Bu df[b]seçim için eşdeğerdir , ancak boolean vektörleri yoluyla atama için de kullanılabilir:

df.loc[b, 'name'] = 'Mary', 'John'

Df.iloc [:,:] tüm satır ve sütunlara eşdeğer mi?
Alvis

Olduğu gibi df.loc[:, :]. Tümünün değerlerini yeniden atamak DataFrameveya bir görünümünü oluşturmak için kullanılabilir.
JoeCondron

merhaba, loc ve iloc'un neden klasik parantez () arasında normal bir yöntem olarak değil, kare parantez [] arasında parametre aldığını biliyor musunuz?
Marine Galantin

119

Bence kabul edilen cevap kafa karıştırıcı, çünkü sadece eksik değerlere sahip bir DataFrame kullanıyor. Ben de terimi sevmiyorum pozisyon bazlı için .ilocve bunun yerine, tercih konuma tamsayı çok daha açıklayıcı ve tam olarak ne kadar .ilocanlamına gelir. Anahtar kelime INTEGER - .ilocINTEGERS gerekiyor.

Daha fazla bilgi için alt küme seçiminde son derece ayrıntılı blog dizimi görün


.ix kullanımdan kaldırıldı ve belirsiz ve asla kullanılmamalıdır

Kullanımdan .ixkaldırıldığı için yalnızca .locve arasındaki farklılıklara odaklanacağız .iloc.

Farklılıklar hakkında konuşmadan önce, DataFrame'lerin her sütunu ve her dizini tanımlamaya yardımcı olan etiketler olduğunu anlamak önemlidir. Örnek bir DataFrame'e bakalım:

df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
                   'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
                   'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
                   'height':[165, 70, 120, 80, 180, 172, 150],
                   'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
                   'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
                   },
                  index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])

resim açıklamasını buraya girin

Kalın yazılmış tüm kelimeler etiketlerdir. Etiketler, age, color, food, height, scoreve statekullanılan sütunlar . Diğer etiketler, Jane, Nick, Aaron, Penelope, Dean, Christina, Corneliakullanılır indeksi .


Bir DataFrame içinde belirli satırları seçmenin birincil yolları .locve .ilocindeksleyicileridir. Bu dizinleyicilerin her biri aynı anda sütunları seçmek için de kullanılabilir, ancak şimdilik satırlara odaklanmak daha kolaydır. Ayrıca, dizinleyicilerin her biri seçimlerini yapmak için adlarını hemen takip eden bir küme parantez kullanır.

.loc verileri yalnızca etiketlerle seçer

Öncelikle, .locyalnızca dizin veya sütun etiketlerine göre veri seçen dizinleyici hakkında konuşacağız . Örnek DataFrame'imizde, dizin için değer olarak anlamlı adlar verdik. Birçok DataFrames anlamlı bir isme sahip olmayacak ve bunun yerine varsayılan olarak sadece 0 ile n-1 arasındaki tamsayıları alacaktır; burada n, DataFrame uzunluğudur.

Kullanabileceğiniz üç farklı giriş var .loc

  • Dizi
  • Dizelerin bir listesi
  • Başlangıç ​​ve bitiş değerleri olarak dizeleri kullanarak dilim gösterimi

Bir dizeyle .loc ile tek bir satır seçme

Tek bir veri satırı seçmek için, dizin etiketini aşağıdaki parantezlerin içine yerleştirin .loc.

df.loc['Penelope']

Bu, veri satırını Seri olarak döndürür

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

Dize listesiyle .loc ile birden çok satır seçme

df.loc[['Cornelia', 'Jane', 'Dean']]

Bu, satırları listede belirtilen sırayla içeren bir DataFrame döndürür:

resim açıklamasını buraya girin

Dilim gösterimiyle .loc ile birden çok satır seçme

Dilim gösterimi bir başlangıç, durdurma ve adım değerleri ile tanımlanır. Etikete göre dilimleme yaparken, pandalar dönüşte durma değerini içerir. Aaron'dan Dean'e aşağıdaki dilimler dahil. Adım boyutu açıkça tanımlanmadı, ancak varsayılan olarak 1.

df.loc['Aaron':'Dean']

resim açıklamasını buraya girin

Karmaşık dilimler, Python listelerinde olduğu gibi alınabilir.

.iloc yalnızca tamsayı konumuna göre veri seçer

Şimdi dönelim .iloc. Bir DataFrame'deki her veri satırı ve sütunu, onu tanımlayan bir tamsayı konumuna sahiptir. Bu, çıktıda görsel olarak görüntülenen etikete ek olarak yapılır . Tamsayı konumu, 0'dan başlayarak üst / soldan başlayan satır / sütun sayısıdır.

Kullanabileceğiniz üç farklı giriş var .iloc

  • Bir tam sayı
  • Tamsayıların listesi
  • Başlangıç ​​ve bitiş değerleri olarak tamsayılar kullanarak dilim gösterimi

.İloc ile bir tamsayı içeren tek bir satır seçme

df.iloc[4]

Bu, 5. satırı (tamsayı konumu 4) Seri olarak döndürür

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

Tam sayı listesiyle .iloc ile birden çok satır seçme

df.iloc[[2, -2]]

Bu, üçüncü ve ikinci ile son satırların DataFrame'lerini döndürür:

resim açıklamasını buraya girin

Dilim gösterimiyle .iloc ile birden çok satır seçme

df.iloc[:5:3]

resim açıklamasını buraya girin


.Loc ve .iloc ile aynı anda satır ve sütun seçimi

Her ikisinin de mükemmel bir yeteneği, .loc/.ilochem satırları hem de sütunları aynı anda seçebilmeleridir. Yukarıdaki örneklerde, tüm sütunlar tüm seçimlerden döndürülmüştür. Satırlar için yaptığımız girişlerin aynısı olan sütunları seçebiliriz. Yalnızca satır ve sütun seçimini virgülle ayırmamız gerekir .

Örneğin, Jane ve Dean satırlarını yalnızca sütun yüksekliği, puanı ve durumuyla aşağıdaki gibi seçebiliriz:

df.loc[['Jane', 'Dean'], 'height':]

resim açıklamasını buraya girin

Bu, satırlar için bir etiket listesi ve sütunlar için dilim gösterimi kullanır

Doğal olarak .ilocsadece tamsayılar kullanarak benzer işlemler yapabiliriz .

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

Etiketler ve tamsayı konumu ile eşzamanlı seçim

.ixetiketler ve tamsayı konumu ile eşzamanlı olarak seçim yapmak için kullanıldı. Bir etiket ve tamsayı konumu karışımıyla seçim yapmanız gerektiğinde, hem seçim etiketlerinizi hem de tamsayı konumlarını yapmanız gerekir.

Örneğin, satırları Nickve Corneliasütun 2 ve 4 ile birlikte seçmek istiyorsak .loc, tamsayıları aşağıdakilere sahip etiketlere dönüştürerek kullanabiliriz :

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

Alternatif olarak, dizin etiketlerini get_locdizin yöntemiyle tamsayılara dönüştürün .

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

Boole Seçimi

.Loc dizinleyici de boole seçimini yapabilir. Örneğin, yaşın 30'un üzerinde olduğu tüm satırları bulmak ve yalnızca foodve scoresütunlarını döndürmek istiyorsak aşağıdakileri yapabiliriz:

df.loc[df['age'] > 30, ['food', 'score']] 

Bunu çoğaltabilirsiniz, .ilocancak bir boolean serisi geçiremezsiniz. Boolean Serisini aşağıdaki gibi bir numpy dizisine dönüştürmelisiniz:

df.iloc[(df['age'] > 30).values, [2, 4]] 

Tüm satırları seçme

.loc/.ilocSadece sütun seçimi için kullanılabilir . Aşağıdaki gibi iki nokta üst üste kullanarak tüm satırları seçebilirsiniz:

df.loc[:, 'color':'score':2]

resim açıklamasını buraya girin


Dizin oluşturma operatörü,, []satırları ve sütunları da seçebilir, ancak aynı anda seçemez.

Çoğu kişi DataFrame indeksleme operatörünün temel amacına aşinadır, bu da sütunları seçmektir. Bir dize, tek bir sütunu Seri olarak seçer ve dizelerin listesi birden çok sütunu DataFrame olarak seçer.

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

Liste kullanmak birden çok sütun seçer

df[['food', 'score']]

resim açıklamasını buraya girin

İnsanların daha az aşina oldukları şey, dilim gösterimi kullanıldığında, seçimin satır etiketleri veya tamsayı konumu ile gerçekleşmesidir. Bu çok kafa karıştırıcı ve neredeyse hiç kullanmadığım bir şey ama işe yarıyor.

df['Penelope':'Christina'] # slice rows by label

resim açıklamasını buraya girin

df[2:6:2] # slice rows by integer location

resim açıklamasını buraya girin

Bir anlaşılırlık .loc/.ilocseçme satırlar için oldukça tercih edilir. Yalnızca dizin oluşturma operatörü, satırları ve sütunları aynı anda seçemez.

df[3:5, 'color']
TypeError: unhashable type: 'slice'

6
Vay be, bu şimdiye kadar bir programlama konusuyla karşılaştığım çok iyi ifade edilmiş ve anlaşılır açıklamalardan biriydi. yöntem. Ben datacamp sahasındaki o boşluğa rastladım. a.) df.columns ve df.index ne döndürür? Dizelerin bir listesi mi? Bir liste ise, bir listede bu df.columns [[2,4]] gibi iki öğeye erişmesine izin verilir mi? b.) df.columns adresinde get_loc () yöntemini çağırabilir miyim? c.) iloc durumunda neden df ['age']> 30. değerlerini çağırmamız gerekir.
pragun

Şimdiye kadar gördüğüm en iyi cevap.
Maksimum

Bu gerçekten iyi bir cevap, itiraf edilen ve derinlere dalmak için anlamsız olan ix'e çok fazla girmemesi hoşuma gitti. Teşekkürler.
omabena
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.