Pandalar'da harita, uygulama haritası ve uygulama yöntemleri arasındaki fark


469

Bu vektörleştirme yöntemlerini ne zaman kullanacağımı temel örneklerle söyleyebilir misiniz?

Bunun mapbir Seriesyöntem olduğunu , geri kalanı ise yöntem olduğunu görüyorum DataFrame. Ama kafam karıştı applyve applymapyöntemler. DataFrame'e bir işlev uygulamak için neden iki yöntemimiz var? Yine, kullanımı gösteren basit örnekler harika olurdu!


5
Yanılıyorsam beni düzeltin, ama bu işlevlerin hepsi uygulandıkları öğeler üzerinde bir döngü içerdiğinden yöntemleri vektörleştirmediğine inanıyorum.
Tanguy

Yanıtlar:


534

Doğrudan Wes McKinney'nin Veri Analizi için Python kitabından, s. 132 (Bu kitabı şiddetle tavsiye ediyorum):

Diğer bir sık ​​işlem, her sütuna veya satıra 1D dizilerine bir işlev uygulamaktır. DataFrame'in uygulama yöntemi tam olarak bunu yapar:

In [116]: frame = DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [117]: frame
Out[117]: 
               b         d         e
Utah   -0.029638  1.081563  1.280300
Ohio    0.647747  0.831136 -1.549481
Texas   0.513416 -0.884417  0.195343
Oregon -0.485454 -0.477388 -0.309548

In [118]: f = lambda x: x.max() - x.min()

In [119]: frame.apply(f)
Out[119]: 
b    1.133201
d    1.965980
e    2.829781
dtype: float64

En yaygın dizi istatistiklerinin birçoğu (toplam ve ortalama gibi) DataFrame yöntemleridir, bu yüzden Apply kullanmak gerekli değildir.

Element-wise Python fonksiyonları da kullanılabilir. Çerçevedeki her bir kayan nokta değerinden biçimlendirilmiş bir dize hesaplamak istediğinizi varsayalım. Bunu mapmap ile yapabilirsiniz:

In [120]: format = lambda x: '%.2f' % x

In [121]: frame.applymap(format)
Out[121]: 
            b      d      e
Utah    -0.03   1.08   1.28
Ohio     0.65   0.83  -1.55
Texas    0.51  -0.88   0.20
Oregon  -0.49  -0.48  -0.31

Applymap adının nedeni, Serilerin öğe bazında bir işlevi uygulamak için bir harita yöntemine sahip olmalarıdır:

In [122]: frame['e'].map(format)
Out[122]: 
Utah       1.28
Ohio      -1.55
Texas      0.20
Oregon    -0.31
Name: e, dtype: object

Özetle apply, bir DataFrame satır / sütun temelinde applymapçalışır, bir DataFrame üzerinde mapelement-wise çalışır ve bir Series üzerinde element-wise çalışır.


31
Kesinlikle konuşmak gerekirse, dahili olarak mapmap, geçirilen işlev parametresinin üzerine biraz sarılmakla uygulanır (kaba bir şekilde yerine funckoymak lambda x: [func(y) for y in x]ve sütun olarak uygulamak)
alko

5
Açıklama için teşekkürler. Beri mapve applymapher ikisi de element-wise, hem Seri hem de DataFrame için çalışacak tek bir yöntem (ya mapda applymap) beklenir. Muhtemelen başka tasarım konuları da var ve Wes McKinney iki farklı yöntem bulmaya karar verdi.
marillion

2
Herhangi bir nedenle kopyamda sayfa 129'da. İkinci baskı ya da başka bir şey için etiket yok.
Jody

1
Pandalarda işlevle applymapbirlikte yapmanın bir yolu var mı groupby?
everestial007

Sütun şeklinde gruplandırılmış verilere bir işlev nasıl uygulanır?
hhh

84

Karşılaştırma map, applymapve : Bağlam Önemlidirapply

İlk büyük fark: TANIM

  • map SADECE Seri'de tanımlanmıştır
  • applymap SADECE DataFrame'lerde tanımlanır
  • apply HER İKİ'de tanımlanmıştır

İkinci büyük fark: INPUT ARGUMENT

  • mapdicts, Seriesveya çağrılabilir kabul eder
  • applymapve applyyalnızca callables'ı kabul edin

Üçüncü büyük fark: DAVRANIŞ

  • map Seri için elementwise
  • applymap DataFrames için elementwise
  • applyaynı zamanda eleman olarak da çalışır, ancak daha karmaşık işlemler ve toplama için uygundur. Davranış ve dönüş değeri işleve bağlıdır.

Dördüncü büyük fark (en önemlisi): KULLANIM ÖRNEĞİ

  • mapdeğerleri bir alandan diğerine eşlemek içindir, dolayısıyla performans için optimize edilmiştir (ör. df['A'].map({1:'a', 2:'b', 3:'c'}))
  • applymapbirden çok satıra / sütuna (ör. df[['A', 'B', 'C']].applymap(str.strip)) yönelik öğe dönüşümlü dönüşümler için iyidir
  • applyvektörleştirilemeyen herhangi bir işlevi uygulamak içindir (ör. df['sentences'].apply(nltk.sent_tokenize))

Özetleme

resim açıklamasını buraya girin

Dipnotlar

  1. mapbir sözlük / Seri iletildiğinde, sözlüğün / Serideki anahtarlara göre öğeleri eşler. Eksik değerler çıkışta NaN olarak kaydedilecektir.
  2. applymapdaha yeni sürümlerde bazı işlemler için optimize edilmiştir. Bazı durumlarda applymapolduğundan biraz daha hızlı bulacaksınız apply. Benim önerim her ikisini de test etmek ve daha iyi olanı kullanmak.

  3. mapelemanlı eşlemeler ve dönüşüm için optimize edilmiştir. Sözlükler veya Seriler içeren işlemler, pandaların daha iyi performans için daha hızlı kod yollarını kullanmasını sağlayacaktır.

  4. Series.applytoplama işlemleri için bir skaler döndürür, aksi takdirde Seri. Benzer şekilde DataFrame.apply. Not applygibi bazı NumPy fonksiyonları ile çağrıldığında da fastpaths sahiptir mean, sumvs.

70

Bu cevaplarda harika bilgiler var, ancak hangi yöntemlerin dizi-bilge ile eleman-bilge olarak çalıştığını açıkça özetlemek için kendime ekliyorum. jeremiahbuddha çoğunlukla bunu yaptı ama Series.apply bahsetmedi. Yorum yapacak temsilcim yok.

  • DataFrame.apply aynı anda tüm satırlarda veya sütunlarda çalışır.

  • DataFrame.applymap,, Series.applyve Series.mapher seferinde bir öğe üzerinde çalışır.

Yetenekleri arasındaki örtüşme çok şey var Series.applyve Series.mapya bir çoğu durumda çalışacak yani. Bununla birlikte, bazıları osa'nın cevabında tartışılan küçük farklılıkları var.


38

Diğer cevaplara ekleyerek, bir Seriesde harita ve başvuru var .

Uygula, bir seriyi DataFrame yapabilir ; ancak, harita sadece başka bir serinin her hücresine bir seri koyacaktır, bu muhtemelen istediğiniz şey değildir.

In [40]: p=pd.Series([1,2,3])
In [41]: p
Out[31]:
0    1
1    2
2    3
dtype: int64

In [42]: p.apply(lambda x: pd.Series([x, x]))
Out[42]: 
   0  1
0  1  1
1  2  2
2  3  3

In [43]: p.map(lambda x: pd.Series([x, x]))
Out[43]: 
0    0    1
1    1
dtype: int64
1    0    2
1    2
dtype: int64
2    0    3
1    3
dtype: int64
dtype: object

Ayrıca "bir web sunucusuna bağlanmak" gibi yan etkileri olan bir fonksiyonum olsaydı, muhtemelen applysadece netlik uğruna kullanırım .

series.apply(download_file_for_every_element) 

Mapyalnızca bir işlevi değil, aynı zamanda bir sözlüğü veya başka bir diziyi de kullanabilir. Diyelim ki permütasyonları değiştirmek istiyorsunuz .

almak

1 2 3 4 5
2 1 4 5 3

Bu permütasyonun karesi

1 2 3 4 5
1 2 5 3 4

Bunu kullanarak hesaplayabilirsiniz map. Kendi kendine başvurunun belgelenip belgelenmediğinden emin değil, ancak çalışıyor 0.15.1.

In [39]: p=pd.Series([1,0,3,4,2])

In [40]: p.map(p)
Out[40]: 
0    0
1    1
2    4
3    2
4    3
dtype: int64

3
Ayrıca, .apply (), .map () yapmazken kwargs işlevine geçmenizi sağlar.
neilxdims

19

@jeremiahbuddha satır / sütunlar üzerinde çalışmaların uygulanacağını, uygulama haritasının ise element olarak çalıştığını belirtti. Ama hala element-wise hesaplama için uygulamak kullanabilirsiniz görünüyor ....

    frame.apply(np.sqrt)
    Out[102]: 
                   b         d         e
    Utah         NaN  1.435159       NaN
    Ohio    1.098164  0.510594  0.729748
    Texas        NaN  0.456436  0.697337
    Oregon  0.359079       NaN       NaN

    frame.applymap(np.sqrt)
    Out[103]: 
                   b         d         e
    Utah         NaN  1.435159       NaN
    Ohio    1.098164  0.510594  0.729748
    Texas        NaN  0.456436  0.697337
    Oregon  0.359079       NaN       NaN

29
Bununla iyi yakala. Bunun örneğinizde çalışmasının nedeni, np.sqrt öğesinin bir ufunc olması, yani bir dizi verirseniz, sqrt işlevini dizinin her öğesine yayınlayacaktır. Bu nedenle, her sütunlarda np.sqrt komutlarını uyguladığınızda, np.sqrt, sütunların her bir öğesinde kendini çalıştırır, bu nedenle, aslında applicationmap ile aynı sonucu alırsınız.
jeremiahbuddha

11

Sadece işaret etmek istedim, bununla biraz uğraşırken

def f(x):
    if x < 0:
        x = 0
    elif x > 100000:
        x = 100000
    return x

df.applymap(f)
df.describe()

bu veri çerçevesini değiştirmez, yeniden atanması gerekir

df = df.applymap(f)
df.describe()

1
Bazen df ile bir şey yaptıktan sonra yeniden atamanız gerekip gerekmediğini anlamakta zorlanıyorum. Çoğunlukla benim için deneme yanılma, ama bahse girerim nasıl çalıştığına dair bir mantık var (kaçırdığım için).
marillion

2
genel olarak, panda veri çerçevesi yalnızca yeniden atanarak df = modified_dfveya inplace=Truebayrak ayarladıysanız değiştirilir . Eğer referans ve fonksiyon tuşelere tarafından bir işleve dataframe bir dataframe geçirirseniz Ayrıca dataframe değişecek
müyon

1
Bu tamamen doğru değil, düşünün .ixya da .wherevs. doğru değil. Yeniden atamanız gerektiğinde ve olmadığında tam açıklamanın ne olduğundan emin değilim.
Thanos

10

Uygula ve uygula arasındaki farkın muhtemelen en basit açıklaması:

Apply , tüm sütunu parametre olarak alır ve ardından sonucu bu sütuna atar

Applymap ayrı hücre değerini parametre olarak alır ve sonucu bu hücreye atar.

Not Eğer uygula, tek bir değer döndürürse, atamadan sonra sütun yerine bu değere sahip olursunuz ve sonunda matris yerine sadece bir satır olur.


3

Benim anlayışım:

İşlev açısından:

İşlev bir sütun / satır içinde karşılaştırılması gereken değişkenlere sahipse, kullanın apply.

örneğin: lambda x: x.max()-x.mean().

İşlev her bir öğeye uygulanacaksa:

1> Bir sütun / satır varsa, apply

2> Tüm veri çerçevesi için geçerliyse, applymap

majority = lambda x : x > 17
df2['legal_drinker'] = df2['age'].apply(majority)

def times10(x):
  if type(x) is int:
    x *= 10 
  return x
df2.applymap(times10)

Kodunuzu test edebilmemiz için lütfen daha iyi netlik için df2'yi de sağlayın.
Ashish Anand

1

Cevabını dayanarak cs95

  • map SADECE Seri'de tanımlanmıştır
  • applymap SADECE DataFrame'lerde tanımlanır
  • apply HER İKİ'de tanımlanmıştır

bazı örnekler ver

In [3]: frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [4]: frame
Out[4]:
            b         d         e
Utah    0.129885 -0.475957 -0.207679
Ohio   -2.978331 -1.015918  0.784675
Texas  -0.256689 -0.226366  2.262588
Oregon  2.605526  1.139105 -0.927518

In [5]: myformat=lambda x: f'{x:.2f}'

In [6]: frame.d.map(myformat)
Out[6]:
Utah      -0.48
Ohio      -1.02
Texas     -0.23
Oregon     1.14
Name: d, dtype: object

In [7]: frame.d.apply(myformat)
Out[7]:
Utah      -0.48
Ohio      -1.02
Texas     -0.23
Oregon     1.14
Name: d, dtype: object

In [8]: frame.applymap(myformat)
Out[8]:
            b      d      e
Utah     0.13  -0.48  -0.21
Ohio    -2.98  -1.02   0.78
Texas   -0.26  -0.23   2.26
Oregon   2.61   1.14  -0.93

In [9]: frame.apply(lambda x: x.apply(myformat))
Out[9]:
            b      d      e
Utah     0.13  -0.48  -0.21
Ohio    -2.98  -1.02   0.78
Texas   -0.26  -0.23   2.26
Oregon   2.61   1.14  -0.93


In [10]: myfunc=lambda x: x**2

In [11]: frame.applymap(myfunc)
Out[11]:
            b         d         e
Utah    0.016870  0.226535  0.043131
Ohio    8.870453  1.032089  0.615714
Texas   0.065889  0.051242  5.119305
Oregon  6.788766  1.297560  0.860289

In [12]: frame.apply(myfunc)
Out[12]:
            b         d         e
Utah    0.016870  0.226535  0.043131
Ohio    8.870453  1.032089  0.615714
Texas   0.065889  0.051242  5.119305
Oregon  6.788766  1.297560  0.860289

0

FOMO:

Aşağıdaki örnek, Şekil applyve applymapbir tatbik DataFrame.

mapişlevi yalnızca Serilere uyguladığınız bir şeydir. Sen uygulayamaz map DataFrame üzerinde.

Hatırlanması gereken şey yani applyyapabileceği şey applymap teneke, ancak applysahip eKStra seçenekleri.

X faktörü seçenekleri şunlardır: axisve result_typenerede result_typeyalnızca çalışır axis=1(sütunlar için).

df = DataFrame(1, columns=list('abc'),
                  index=list('1234'))
print(df)

f = lambda x: np.log(x)
print(df.applymap(f)) # apply to the whole dataframe
print(np.log(df)) # applied to the whole dataframe
print(df.applymap(np.sum)) # reducing can be applied for rows only

# apply can take different options (vs. applymap cannot)
print(df.apply(f)) # same as applymap
print(df.apply(sum, axis=1))  # reducing example
print(df.apply(np.log, axis=1)) # cannot reduce
print(df.apply(lambda x: [1, 2, 3], axis=1, result_type='expand')) # expand result

Bir sidenote olan Seri mapfonksiyonu, Python mapfonksiyonu ile karıştırılmamalıdır .

İlki, değerleri eşlemek için Seri'ye uygulanır, ikincisi de yinelenebilir her öğeye uygulanır.


Son olarak dataframe applyyöntemini groupby yöntemiyle karıştırmayın apply.

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.