ความแตกต่างระหว่างแผนที่, Applymap และวิธีการใช้ใน Pandas


465

คุณสามารถบอกฉันได้เมื่อใดที่จะใช้วิธีการเวกเตอร์เหล่านี้กับตัวอย่างพื้นฐาน?

ฉันเห็นว่าmapเป็นSeriesวิธีการในขณะที่ส่วนที่เหลือเป็นDataFrameวิธีการ ฉันสับสนapplyและapplymapวิธีการต่าง ๆ ทำไมเรามีสองวิธีในการใช้ฟังก์ชั่นกับ DataFrame อีกครั้งตัวอย่างง่ายๆที่แสดงการใช้งานจะยอดเยี่ยม!


5
แก้ไขให้ถูกต้องหากฉันผิด แต่ฉันเชื่อว่าฟังก์ชั่นเหล่านั้นไม่ใช่วิธีการปรับเวกเตอร์เนื่องจากทุกอย่างเกี่ยวข้องกับการวนรอบองค์ประกอบที่ใช้
Tanguy

1
ฉันไม่เห็นความแตกต่างที่นี่: gist.github.com/MartinThoma/e320cbb937afb4ff766f75988f1c65e6
Martin Thoma

คำตอบ:


533

ส่งตรงจากPythonของ Wes McKinney สำหรับหนังสือData Analysis , pg. 132 (ฉันขอแนะนำหนังสือเล่มนี้):

การดำเนินการบ่อยครั้งอื่นคือการใช้ฟังก์ชันบนอาร์เรย์ 1D กับแต่ละคอลัมน์หรือแถว วิธีการใช้ DataFrame ทำสิ่งนี้ทุกประการ

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

สถิติอาร์เรย์ที่พบมากที่สุดจำนวนมาก (เช่นผลรวมและค่าเฉลี่ย) เป็นวิธี DataFrame ดังนั้นจึงไม่จำเป็นต้องใช้การใช้

สามารถใช้ฟังก์ชั่น Python ที่ชาญฉลาดขององค์ประกอบได้เช่นกัน สมมติว่าคุณต้องการคำนวณสตริงที่จัดรูปแบบจากค่าทศนิยมแต่ละจุดในเฟรม คุณสามารถทำได้ด้วย Applymap:

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 คือ Series มีวิธีการแผนที่สำหรับการใช้ฟังก์ชั่นองค์ประกอบที่ฉลาด:

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

สรุปรวมapplyทำงานบนพื้นฐานแถว / คอลัมน์ของ DataFrame applymapทำงานองค์ประกอบที่ชาญฉลาดใน DataFrame และmapทำงานองค์ประกอบที่ฉลาดในซีรีส์


31
อย่างเคร่งครัดพูด applymap ภายในจะดำเนินการผ่านทางนำไปใช้กับการห่อขึ้นพารามิเตอร์ของฟังก์ชันเล็ก ๆ น้อย ๆ ผ่าน (rougly พูดเปลี่ยนfuncไปlambda x: [func(y) for y in x]และการประยุกต์ใช้คอลัมน์ฉลาด)
Alko

5
ขอบคุณสำหรับคำอธิบาย ตั้งแต่mapและapplymapทั้งองค์ประกอบการทำงานที่ชาญฉลาดฉันคาดว่าจะมีวิธีการเดียว (อย่างใดอย่างหนึ่งmapหรือapplymap) ซึ่งจะทำงานได้ทั้งกับ Series และ DataFrame อาจมีข้อควรพิจารณาในการออกแบบอื่น ๆ และ Wes McKinney ตัดสินใจใช้วิธีการที่แตกต่างกันสองวิธี
marillion

2
มันอยู่ในหน้า 129 ในสำเนาของฉันด้วยเหตุผลบางอย่าง ไม่มีฉลากสำหรับรุ่นที่สองหรืออะไร
โจดี้

1
มีวิธีที่จะทำอย่างไรapplymapกับgroupbyฟังก์ชั่นในนุ่น?
everestial007

วิธีการใช้ฟังก์ชั่นกับข้อมูลคอลัมน์แบบกลุ่ม?
hhh

83

เปรียบเทียบmap, applymapและ: เรื่องบริบทapply

ความแตกต่างที่สำคัญประการแรก: ความหมาย

  • map ถูกกำหนดในซีรี่ส์เท่านั้น
  • applymap ถูกกำหนดไว้ใน DataFrames เท่านั้น
  • apply ถูกกำหนดบนทั้งสอง

ความแตกต่างที่สำคัญที่สอง: ARPUMG INPUT

  • mapยอมรับdicts Series, หรือ callable
  • applymapและapplyยอมรับ callables เท่านั้น

ความแตกต่างหลักที่สาม: พฤติกรรม

  • map เป็นองค์ประกอบสำหรับซีรีย์
  • applymap เป็นองค์ประกอบสำหรับ DataFrames
  • applyยังทำงานได้ตามองค์ประกอบ แต่เหมาะสมกับการดำเนินงานและการรวมที่ซับซ้อนมากขึ้น พฤติกรรมและค่าตอบแทนขึ้นอยู่กับฟังก์ชัน

ความแตกต่างหลักที่สี่ (สำคัญที่สุด): ใช้กรณี

  • mapมีไว้สำหรับการจับคู่ค่าจากโดเมนหนึ่งไปอีกโดเมนหนึ่งดังนั้นจึงเหมาะสำหรับประสิทธิภาพ (เช่นdf['A'].map({1:'a', 2:'b', 3:'c'}))
  • applymapเป็นสิ่งที่ดีสำหรับการแปลงแบบองค์ประกอบตามแนวขวางในหลายแถว / คอลัมน์ (เช่นdf[['A', 'B', 'C']].applymap(str.strip))
  • applyใช้สำหรับฟังก์ชั่นใด ๆ ที่ไม่สามารถใช้เวกเตอร์ได้ (เช่นdf['sentences'].apply(nltk.sent_tokenize))

สรุป

ป้อนคำอธิบายรูปภาพที่นี่

เชิงอรรถ

  1. mapเมื่อผ่านพจนานุกรม / ซีรีส์จะแมปองค์ประกอบตามปุ่มในพจนานุกรม / ซีรีย์นั้น ค่าที่หายไปจะถูกบันทึกเป็น NaN ในเอาต์พุต
  2. applymapในเวอร์ชันล่าสุดได้รับการปรับให้เหมาะกับการใช้งานบางอย่าง คุณจะพบว่าapplymapเร็วกว่าapplyในบางกรณีเล็กน้อย ข้อเสนอแนะของฉันคือการทดสอบพวกเขาทั้งสองและใช้สิ่งที่ดีกว่า

  3. mapได้รับการปรับให้เหมาะสมสำหรับการแมปและการเปลี่ยนแปลงแบบวน การดำเนินการที่เกี่ยวข้องกับพจนานุกรมหรือซีรี่ส์จะทำให้แพนด้าสามารถใช้โค้ดพา ธ ที่เร็วขึ้นเพื่อประสิทธิภาพที่ดียิ่งขึ้น

  4. Series.applyส่งคืนสเกลาร์สำหรับการดำเนินการรวม Series เป็นอย่างอื่น DataFrame.applyในทำนองเดียวกันสำหรับ โปรดทราบว่าapplyยังมี fastpaths เมื่อเรียกใช้ด้วยฟังก์ชัน NumPy บางอย่างเช่นmean,, sumและอื่น ๆ

70

มีข้อมูลที่ดีในคำตอบเหล่านี้ แต่ฉันเพิ่มของฉันเองเพื่อสรุปอย่างชัดเจนว่าวิธีใดทำงานกับอาเรย์ที่ชาญฉลาดเมื่อเทียบกับองค์ประกอบที่ชาญฉลาด jeremiahbuddha ส่วนใหญ่ทำสิ่งนี้ แต่ไม่ได้พูดถึง Series.apply ฉันไม่มีตัวแทนที่จะแสดงความคิดเห็น

  • DataFrame.apply ดำเนินการกับแถวหรือคอลัมน์ทั้งหมดในเวลาเดียวกัน

  • DataFrame.applymap, Series.applyและSeries.mapดำเนินการกับองค์ประกอบหนึ่งอย่างในเวลาเดียวกัน

มีการทับซ้อนกันมากมายระหว่างความสามารถของSeries.applyและSeries.mapซึ่งหมายความว่าจะใช้งานได้ในกรณีส่วนใหญ่ พวกเขามีความแตกต่างเล็กน้อยบางอย่างซึ่งบางส่วนถูกกล่าวถึงในคำตอบของ osa


38

เพิ่มไปยังคำตอบอื่น ๆ ในSeriesนอกจากนี้ยังมีแผนที่และนำไปใช้นำไปใช้

สมัครสามารถทำให้ DataFrame ออกจากชุด ; อย่างไรก็ตามแผนที่จะใส่ซีรี่ส์ในทุกเซลล์ของซีรี่ส์อื่นซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ

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

นอกจากนี้ถ้าฉันมีฟังก์ชั่นที่มีผลข้างเคียงเช่น "เชื่อมต่อกับเว็บเซิร์ฟเวอร์" ฉันอาจใช้applyเพียงเพื่อความชัดเจน

series.apply(download_file_for_every_element) 

Mapสามารถใช้ไม่เพียง แต่ฟังก์ชั่น แต่ยังรวมถึงพจนานุกรมหรือซีรี่ส์อื่น สมมติว่าคุณต้องการที่จะจัดการกับพีชคณิต

เอา

1 2 3 4 5
2 1 4 5 3

กำลังสองของการเปลี่ยนรูปนี้คือ

1 2 3 4 5
1 2 5 3 4

mapคุณสามารถคำนวณได้โดยใช้ ไม่แน่ใจว่ามีการบันทึกแอปพลิเคชันด้วยตนเองหรือไม่ แต่ทำงาน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
นอกจากนี้. apply () ให้คุณส่งผ่าน kwargs เข้าไปในฟังก์ชันในขณะที่. map () ไม่ได้
neilxdims

19

@jeremiahbuddha กล่าวถึงว่าการใช้ผลงานในแถว / คอลัมน์ในขณะที่การประยุกต์ใช้การทำงานขององค์ประกอบที่ชาญฉลาด แต่ดูเหมือนว่าคุณยังสามารถใช้ใช้สำหรับการคำนวณองค์ประกอบที่ชาญฉลาด ....

    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
จับได้ดีกับสิ่งนี้ เหตุผลที่การทำงานในตัวอย่างของคุณเป็นเพราะ np.sqrt เป็น ufunc นั่นคือถ้าคุณให้อาร์เรย์มันจะกระจายฟังก์ชัน sqrt ไปยังแต่ละองค์ประกอบของอาร์เรย์ ดังนั้นเมื่อใช้ pushes np.sqrt ในแต่ละคอลัมน์ np.sqrt จะทำงานด้วยตัวเองในแต่ละองค์ประกอบของคอลัมน์ดังนั้นคุณจะได้รับผลลัพธ์เช่นเดียวกับ Applymap
jeremiahbuddha

11

แค่อยากจะชี้ให้เห็นในขณะที่ฉันต่อสู้กับเรื่องนี้สักหน่อย

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

df.applymap(f)
df.describe()

สิ่งนี้ไม่ได้แก้ไขดาตาเฟรมเองต้องได้รับการกำหนดใหม่

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

1
บางครั้งฉันมีปัญหาในการหาว่าคุณต้องมอบหมายใหม่หรือไม่หลังจากทำบางสิ่งกับ df ส่วนใหญ่จะเป็นการทดลองและข้อผิดพลาดสำหรับฉัน แต่ฉันคิดว่ามันมีเหตุผลในการทำงาน (ที่ฉันพลาด)
marillion

2
โดยทั่วไปแล้ว dataframe ของ pandas จะถูกแก้ไขโดยการกำหนดใหม่df = modified_dfหรือถ้าคุณตั้งค่าinplace=Trueสถานะ นอกจากนี้ dataframe ก็จะเปลี่ยนไปถ้าคุณส่ง dataframe ไปยังฟังก์ชั่นโดยการอ้างอิงและฟังก์ชั่นปรับเปลี่ยน dataframe
muon

1
สิ่งนี้ไม่เป็นความจริงทั้งหมดคิด.ixหรือ.whereอื่น ๆ ไม่แน่ใจว่าคำอธิบายแบบเต็มรูปแบบนั้นมีไว้เพื่ออะไรเมื่อคุณต้องการมอบหมายใหม่และเมื่อไม่ต้องการ
ธานอส

10

คำอธิบายที่ง่ายที่สุดน่าจะเป็นความแตกต่างระหว่างการใช้และการประยุกต์ใช้:

ใช้นำคอลัมน์ทั้งหมดมาเป็นพารามิเตอร์แล้วกำหนดผลลัพธ์ให้กับคอลัมน์นี้

Applymapใช้ค่าของเซลล์ที่แยกต่างหากเป็นพารามิเตอร์และกำหนดผลลัพธ์กลับไปที่เซลล์นี้

NB ถ้าใช้ส่งคืนค่าเดียวคุณจะมีค่านี้แทนคอลัมน์หลังจากกำหนดและในที่สุดจะมีเพียงแถวแทนเมทริกซ์


3

ความเข้าใจของฉัน:

จากมุมมองฟังก์ชั่น:

ถ้าฟังก์ชันมีตัวแปรที่ต้องเปรียบเทียบภายในคอลัมน์ / แถว, applyการใช้งาน

lambda x: x.max()-x.mean()เช่น:

หากฟังก์ชั่นนี้จะใช้กับแต่ละองค์ประกอบ:

1> หากมีคอลัมน์ / แถวให้ใช้ apply

2> หากนำไปใช้กับทั้ง dataframe ให้ใช้ 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)

โปรดระบุ df2 เพื่อความชัดเจนที่ดีขึ้นเพื่อให้เราสามารถทดสอบรหัสของคุณได้
Ashish Anand

1

ตามคำตอบของcs95

  • map ถูกกำหนดในซีรี่ส์เท่านั้น
  • applymap ถูกกำหนดไว้ใน DataFrames เท่านั้น
  • apply ถูกกำหนดบนทั้งสอง

ยกตัวอย่าง

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:

แสดงให้เห็นตัวอย่างต่อไปนี้applyและนำไปใช้applymapDataFrame

mapfunction เป็นสิ่งที่คุณใช้กับซีรี่ส์เท่านั้น คุณไม่สามารถใช้map กับ DataFrame

สิ่งที่ต้องจำคือ applyสามารถทำทุกอย่าง ได้applymapแต่applyมีตัวเลือกeXtra

ตัวเลือก X ปัจจัย ได้แก่ : axisและresult_typeที่result_typeทำงานเฉพาะเมื่อaxis=1(สำหรับคอลัมน์)

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

ในฐานะ sidenote mapฟังก์ชันSeries ไม่ควรสับสนกับmapฟังก์ชันPython

คนแรกถูกนำไปใช้ในซีรีส์เพื่อแมปค่าและคนที่สองกับทุกรายการของ iterable


สุดท้ายอย่าสับสนกับ dataframe applyวิธีการด้วยapplyวิธีการgroupby

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.