Pandalar: Tek bir sütun için Apply () işlevini nasıl kullanabilirim?


260

İki sütunlu bir panda veri çerçevem ​​var. Ben ikincisini etkilemeden ilk sütunun değerlerini değiştirmek ve sadece ilk sütun değerleri değişti ile tüm veri çerçevesini geri almak gerekiyor. Pandalarda uygulamak için bunu nasıl yapabilirim?


4
Lütfen bazı girdi örnek verilerini ve istenen çıktıyı gönderin.
Fabio Lamanna

Neredeyse asla applyböyle bir durumda kullanmamalısınız . Bunun yerine doğrudan sütunu kullanın.
Ted Petrou

Ted Petrou'nun dediği applygibi, mümkün olduğunca kullanmaktan kaçının . Kullanmanız gerektiğinden emin değilseniz muhtemelen kullanmıyorsunuzdur. Kodumda ne zaman panda uygula () kullanmak istersem? .
cs95

Soru tam olarak açık değil: bir sütunun her elemanına bir fonksiyon mu uyguluyor mu yoksa bir bütün olarak sütuna bir fonksiyon mu uyguluyor (örneğin: sütunu tersine çeviriyor)?
Pierre ALBARÈDE

Yanıtlar:


339

Aşağıdaki dfgibi bir örnek veri çerçevesi verildi:

a,b
1,2
2,3
3,4
4,5

ne istiyorsun:

df['a'] = df['a'].apply(lambda x: x + 1)

döndüren:

   a  b
0  2  2
1  3  3
2  4  4
3  5  5

9
applyasla böyle bir durumda kullanılmamalıdır
Ted Petrou

5
@TedPetrou mükemmel haklısınız, bu OP'nin istediği gibi genel bir işlevin tek bir sütuna nasıl uygulanacağına sadece bir örnekti.
Fabio Lamanna

14
"Bir değer bir DataFrame bir dilim bir kopyası ayarlanabilir çalışıyor yerine .loc [row_indexer, col_indexer] = değeri kullanılarak deneyin": Ben bunu yapmaya çalışırken aşağıdaki uyarıyı almak
dagrun

24
Bir merak olarak: neden bu durumda kullanılmamalıdır? Durum tam olarak nedir?
Ben Ben Amca

19
@BenzersizBenBen genel olarak apply, örneğin vektörleştirilmiş işlevlerden çok daha yavaş olan satırlar üzerinde dahili bir döngü kullanır, örneğin df.a = df.a / 2(bkz. Mike Muller cevabı).
Fabio Lamanna

67

Tek bir sütunun daha iyi kullanılması için map(), şöyle:

df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9



df['a'] = df['a'].map(lambda a: a / 2.)

      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

78
Neden tek bir sütundan map()daha iyidir apply()?
ChaimG

2
Bu çok faydalı oldu. Bir sütunda saklanan yollardan dosya adlarını ayıklamak için kullandımdf['file_name'] = df['Path'].map(lambda a: os.path.basename(a))
mmann1123

46
map (), Series (yani tek sütunlar) içindir ve her seferinde tek bir hücre üzerinde çalışır.
jpcgt

4
@jpcgt Bu, haritanın bu durumda uygulanmasından daha hızlı olduğu anlamına mı geliyor?
Viragos

@ChaimG i bu os iyi açıklıyor görmek: stackoverflow.com/a/19798528/571828
象 嘉 道

41

Hiç bir işleve ihtiyacınız yok. Doğrudan bir sütun üzerinde çalışabilirsiniz.

Örnek veriler:

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

Sütundaki tüm değerlerin yarısı a:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

Bir sütundaki her öğeyi "/" ile bölmek ve ilk bölümü almak istersem ne olur?
K47

12

Verilen yanıtlar doğru olmakla birlikte, her zaman arzu edilmeyen ilk veri çerçevesini değiştirirler (ve OP'nin "kullanarak apply" örnek istediği düşünüldüğünde, yeni bir veri çerçevesini döndüren bir sürüm istediği gibi olabilir apply).

Bu şu şekilde mümkündür assign: assignbelgelerin belirttiği gibi mevcut sütunlar için geçerlidir (vurgu benimdir):

Bir DataFrame'e yeni sütunlar atayın.

Yenilerine ek olarak tüm orijinal sütunları içeren yeni bir nesne döndürür . Yeniden atanan mevcut sütunların üzerine yazılacaktır .

Kısacası:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

In [3]: df.assign(a=lambda df: df.a / 2)
Out[3]: 
      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

In [4]: df
Out[4]: 
    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9

Fonksiyonun yalnızca değiştirmek istediğiniz sütuna değil, tüm veri çerçevesine aktarılacağını unutmayın, bu nedenle lambda'nızda doğru sütunu seçtiğinizden emin olmanız gerekecektir.


9

Uygulama işlevinizin yürütme hızıyla ilgili endişeleriniz varsa ve üzerinde çalışmak için çok büyük bir veri kümeniz varsa, daha hızlı yürütme yapmak için kaydırıcıyı kullanabilirsiniz, burada panda veri çerçevesindeki kaydırıcıya bir örnek:

import pandas as pd
import swifter

def fnc(m):
    return m*3+4

df = pd.DataFrame({"m": [1,2,3,4,5,6], "c": [1,1,1,1,1,1], "x":[5,3,6,2,6,1]})

# apply a self created function to a single column in pandas
df["y"] = df.m.swifter.apply(fnc)

Bu, tüm CPU çekirdeklerinizin sonucu hesaplamasını sağlar, bu nedenle normal uygulama işlevlerinden çok daha hızlı olacaktır. Sizin için faydalı olup olmadığını bana bildirin.


1

Tarih saatini kullanarak ve boş veya boş alanlar düşünerek karmaşık bir hesaplamayı deneyeyim. Bir datetime sütununda 30 yılı azaltıyorum ve applyyöntemi kullanarak lambdave datetime biçimini dönüştürüyorum. Hat if x != '' else x, tüm boş alanlara veya boş değerlere uygun olarak ilgilenecektir.

df['Date'] = df['Date'].fillna('')
df['Date'] = df['Date'].apply(lambda x : ((datetime.datetime.strptime(str(x), '%m/%d/%Y') - datetime.timedelta(days=30*365)).strftime('%Y%m%d')) if x != '' else x)
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.