Panda veri çerçevesinde bir satır alt kümesini değiştirme


143

A ve B olmak üzere iki sütunlu bir panda DataFrame'im olduğunu varsayalım. Bu DataFrame'i değiştirmek (veya bir kopya oluşturmak), böylece A 0 olduğunda B her zaman NaN olur.

Aşağıdakileri denedim

df['A'==0]['B'] = np.nan

ve

df['A'==0]['B'].values.fill(np.nan)

başarısız.


Çok hızlı bir çözüm arıyorsanız NumPy's'i aşağıdaki bu çözümdewhere görüldüğü gibi kullanın
Ted Petrou

Yanıtlar:


243

.locEtiket tabanlı indeksleme için kullanın :

df.loc[df.A==0, 'B'] = np.nan

df.A==0İfade endeksleri satırlar, bu bir boolean dizi oluşturur 'B'sütunu seçer. Bunu, bir sütunun alt kümesini dönüştürmek için de kullanabilirsiniz, örneğin:

df.loc[df.A==0, 'B'] = df.loc[df.A==0, 'B'] / 2

Tam olarak neden işe yaradığını bilmek panda iç hakkında yeterli bilmiyorum, ancak temel sorun bazen bir DataFrame içine dizinleme sonucunun bir kopyasını döndürür ve bazen orijinal nesne üzerinde bir görünüm döndürür. Buradaki belgelere göre , bu davranış altta yatan numpy davranışına bağlıdır. Her şeye tek bir işlemde erişmenin ([bir] [iki] yerine) ayar için işe yarama olasılığının daha yüksek olduğunu gördüm.


Bunun ikinci kısmı bile sorulmamış bir soruya güzel bir cevap ;-) Ben hala kanonik pandalar cevap olup olmadığını merak ediyorum, özellikle b / c açık bir KURU ihlali, ama içinde olduğunu varsayalım pandaların iç kısıtlamaları göz önüne alındığında DRY'yi ihlal etmek için gerekli olan gerçek nedir? (Bu tür bir soruyu daha ayrıntılı olarak gönderebilirim, ancak bunu yapmadan önce hızlı bir cevabınız olup olmadığını görmek istedim)
JohnE

Sütun adlarına sahip olmayan bir Dataframe alt kümesi nasıl df sadece dizin tarafından alt kümesi? df.loc [df [0] == 0] çalışmıyor ... Alternatif nedir? Thank You
amipro

89

İşte gelişmiş endeksleme üzerinde panda dokümanlardan geçerli:

Bu bölüm tam olarak neye ihtiyacınız olduğunu açıklayacaktır! Çıkıyor df.loc(.ix kullanımdan kaldırıldı olarak - aşağıda belirttiğimiz birçok gibi) bir dataframe ait zar atıyor / serin dilimleme için kullanılabilir. Ve. Bir şeyleri ayarlamak için de kullanılabilir.

df.loc[selection criteria, columns I want] = value

Bren'in cevabı, 'beni tüm yerleri bul df.A == 0, sütun seç Bve np.nan'


2
Günümü gün ettin. Açık bir açıklama.
TwinPenguins

1
Evet, bir şekilde loc[selection criteria, columns I want]aklına mükemmel bir şekilde yapışıyor ...
EmEs

29

Pandalar 0.20 ix'den itibaren kullanımdan kaldırıldı . Doğru yol df.loc kullanmaktır

İşte çalışan bir örnek

>>> import pandas as pd 
>>> import numpy as np 
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
   A   B
0  0 NaN
1  1   0
2  0 NaN
>>> 

Açıklama:

Dokümana açıklandığı gibi burada , .loc öncelikle temel etiketlemek, aynı zamanda, bir Boole dizi ile kullanılabilir .

Yukarıda yaptığımız şey şu şekildedir df.loc[row_index, column_index]:

  • locBoole dizisini pandalara hangi satırları değiştirmek istediğimizi söyleyen bir maske olarak alabilecek gerçeği kullanmakrow_index
  • Gerçekleri lockullanmak ayrıca 'B',column_index

Mantıksal, koşul veya boolean dizisini oluşturmak için bir dizi boolean döndüren herhangi bir işlemi kullanabiliriz. Yukarıdaki örnekte, aşağıdaki örnekte de görebileceğiniz gibi , kullanabileceğimiz rowsbir içeren bir tane istiyoruz , bu bir dizi boolean döndürür. 0df.A == 0

>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df 
   A  B
0  0  2
1  1  0
2  0  5
>>> df.A == 0 
0     True
1    False
2     True
Name: A, dtype: bool
>>> 

Ardından, gerekli satırları seçmek ve değiştirmek için yukarıdaki booleans dizisini kullanırız:

>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
   A   B
0  0 NaN
1  1   0
2  0 NaN

Daha fazla bilgi için gelişmiş indeksleme belgelerini kontrol buraya .


11

Devasa bir hız artışı için NumPy'nin burada işlevini kullanın.

Kurmak

Bazı sıfırlarla 100.000 satır içeren iki sütunlu bir DataFrame oluşturun.

df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab'))

İle hızlı çözüm numpy.where

df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)

zamanlamalar

%timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.loc[df['a'] == 0, 'b'] = np.nan
3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Numpy's whereyaklaşık 4 kat daha hızlı


Bunu merak ettim, bu yüzden kendim test ettim ve fark diğer parametreleri kullanarak daha da büyüktü. Numpy, 0'ları np.nan yerine bir tamsayı ile değiştirirken neredeyse 10 kat daha hızlıydı. Fazladan zamanın ne olduğunu merak ediyorum.
Alexander

Kullanmak gerekli midir .valuesiçinde np.where(df.a.values == 0, np.nan, df.b.values)? np.where(df.a == 0, np.nan, df.b)Ayrıca çalışıyor gibi görünüyor ?
hsl

4

Birden çok sütunu değiştirmek için aşağıdakileri kullanarak numpy dizisine dönüştürün .values:

df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
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.