ความคลุมเครือในนิยาม "แกน" ของ Pandas Dataframe / Numpy Array


93

ฉันสับสนมากเกี่ยวกับวิธีกำหนดแกน python และอ้างถึงแถวหรือคอลัมน์ของ DataFrame หรือไม่ พิจารณารหัสด้านล่าง:

>>> df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], columns=["col1", "col2", "col3", "col4"])
>>> df
   col1  col2  col3  col4
0     1     1     1     1
1     2     2     2     2
2     3     3     3     3

ดังนั้นถ้าเราเรียกdf.mean(axis=1)เราจะได้ค่าเฉลี่ยในแถว:

>>> df.mean(axis=1)
0    1
1    2
2    3

อย่างไรก็ตามหากเราโทรdf.drop(name, axis=1)ไปเราจะวางคอลัมน์ไม่ใช่แถว:

>>> df.drop("col4", axis=1)
   col1  col2  col3
0     1     1     1
1     2     2     2
2     3     3     3

ใครช่วยฉันเข้าใจความหมายของ "แกน" ในแพนด้า / numpy / scipy

หมายเหตุด้านข้างDataFrame.meanอาจกำหนดผิด ในเอกสารระบุDataFrame.meanว่าaxis=1ควรจะหมายถึงค่าเฉลี่ยเหนือคอลัมน์ไม่ใช่แถว ...


สำหรับคำอธิบายรายละเอียดของการนามแฝง'คอลัมน์'และ'ดัชนี' / 'แถว' ดูคำตอบด้านล่างนี้
Ted Petrou

นี่เป็นเรื่องแปลก แกนควรจะสอดคล้องข้ามและmean dropต้องใช้ความคิดแบบไม่เชิงเส้นเพื่อให้ได้พฤติกรรมที่แท้จริง
StephenBoesch

คำตอบ:


169

มันอาจจะง่ายที่สุดในการจำได้ว่ามันเป็น0 = ลงและ1 = ข้าม

ซึ่งหมายความว่า:

  • ใช้axis=0เพื่อใช้วิธีการลงในแต่ละคอลัมน์หรือกับป้ายชื่อแถว (ดัชนี)
  • ใช้axis=1เพื่อใช้วิธีการในแต่ละแถวหรือกับป้ายชื่อคอลัมน์

นี่คือภาพแสดงส่วนต่างๆของ DataFrame ที่แต่ละแกนอ้างถึง:

นอกจากนี้ยังเป็นประโยชน์ที่จะจำไว้ว่าต่อไปนี้นุ่นใช้ NumPy axisของคำว่า การใช้งานมีอธิบายไว้ในอภิธานศัพท์ของ NumPy :

แกนถูกกำหนดสำหรับอาร์เรย์ที่มีมิติข้อมูลมากกว่าหนึ่งมิติ อาร์เรย์ 2 มิติมีสองแกนที่สอดคล้องกัน: การทำงานครั้งแรกในแนวตั้งลงในแถว (แกน 0)และที่สองทำงานในแนวนอนคอลัมน์ (แกน 1) [ ความสำคัญของฉัน ]

ดังนั้นเกี่ยวกับวิธีการในคำถามdf.mean(axis=1)ดูเหมือนจะกำหนดไว้อย่างถูกต้อง ใช้ค่าเฉลี่ยของรายการในแนวนอนข้ามคอลัมน์นั่นคือตามแต่ละแถว บนมืออื่น ๆ ที่df.mean(axis=0)จะมีการดำเนินการทำหน้าที่ในแนวตั้งลงในแถว

ในทำนองเดียวกันdf.drop(name, axis=1)หมายถึงการกระทำบนป้ายชื่อคอลัมน์เนื่องจากโดยสัญชาตญาณจะข้ามแกนแนวนอน การระบุaxis=0จะทำให้เมธอดดำเนินการกับแถวแทน


3
สิ่งที่ทำให้ฉันต้องดิ้นรนก็คือ df.apply (... , axis = 0) ไม่ "วิ่งทับ" แกน 0 (ดัชนี) แต่วิ่งไปที่คอลัมน์โดยยึด Series ที่มีดัชนีทั้งหมด เบาะแสคือ df.apply (... , axis = 0) ส่งกลับ Series เพื่อให้คุณสามารถใช้การดำเนินการที่รันบนดัชนีทั้งหมดได้
moritzschaefer

2
ฉันคิดว่ามันช่วยได้df.applyเช่นกันหากคุณดูคล้ายกับวิธีการเช่นdf.sum. ตัวอย่างเช่นdf.sum(axis=0)ผลรวมแต่ละคอลัมน์ของ DataFrame ในทำนองเดียวกันคุณสามารถเขียนdf.apply(sum, axis=0)ให้ดำเนินการเดียวกันทุกประการ แม้ว่าการดำเนินการจะถูกนำไปใช้กับแต่ละคอลัมน์ใน DataFrame แต่ฟังก์ชันจริงจะทำงานตามแกน 0
Alex Riley

โชคไม่ดีที่รูปแบบการตั้งชื่อและลำดับตรงข้ามกับฟังก์ชันใช้งานของ R - ใน R ค่าที่ต่ำกว่าMARGIN(คล้ายกับaxisหมีแพนด้า) ของ "1" จะตรงกับ "แถว" ซึ่งหมายความว่าฟังก์ชันจะถูกนำไปใช้กับแต่ละแถวในขณะที่ ค่าขนาดใหญ่ของ "2" หมายถึง "คอลัมน์" ซึ่งหมายความว่าฟังก์ชั่นที่มีการใช้ในแต่ละคอลัมน์
Keith Hughitt

มันเป็นแมลงที่ทำลายล้างในหมีแพนด้า
Calculus

10

อีกวิธีหนึ่งในการอธิบาย:

// Not realistic but ideal for understanding the axis parameter 
df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]],
                  columns=["idx1", "idx2", "idx3", "idx4"],
                  index=["idx1", "idx2", "idx3"]
                 )

---------------------------------------1
|          idx1  idx2  idx3  idx4
|    idx1     1     1     1     1
|    idx2     2     2     2     2
|    idx3     3     3     3     3
0

เกี่ยวกับdf.drop(แกนหมายถึงตำแหน่ง)

A: I wanna remove idx3.
B: **Which one**? // typing while waiting response: df.drop("idx3",
A: The one which is on axis 1
B: OK then it is >> df.drop("idx3", axis=1)

// Result
---------------------------------------1
|          idx1  idx2     idx4
|    idx1     1     1     1
|    idx2     2     2     2
|    idx3     3     3     3
0

About df.apply(แกนหมายถึงทิศทาง)

A: I wanna apply sum.
B: Which direction? // typing while waiting response: df.apply(lambda x: x.sum(),
A: The one which is on *parallel to axis 0*
B: OK then it is >> df.apply(lambda x: x.sum(), axis=0)

// Result
idx1    6
idx2    6
idx3    6
idx4    6

คุณไม่คิดว่าบนแกน 1 และขนานกับแกน 0 หมายความว่าเหมือนกัน
Nuance

9

มีคำตอบที่เหมาะสมอยู่แล้ว แต่ขอยกตัวอย่างอีกตัวอย่างหนึ่งที่มี> 2 มิติ

พารามิเตอร์axisหมายถึงแกนจะมีการเปลี่ยนแปลง
ตัวอย่างเช่นพิจารณาว่ามี dataframe กับมิติaxbxc

  • df.mean(axis=1)ผลตอบแทน dataframe กับ dimenstion ขวาน 1 XC
  • df.drop("col4", axis=1)ผลตอบแทนที่ได้ dataframe กับมิติขวาน (B-1) XC

ในที่นี้axis=1หมายถึงแกนที่สองซึ่งเป็นbดังนั้นbค่าจะเปลี่ยนไปในตัวอย่างเหล่านี้


1
คำตอบนี้เข้าใจง่ายสำหรับฉันมากกว่าการแสดงภาพใด ๆ ที่ฉันเห็นในหัวข้อนี้ อย่างไรก็ตาม xarray ดีกว่าสำหรับอาร์เรย์หลายมิติมากกว่าแพนด้า
alys

2

ควรเป็นที่ทราบกันอย่างแพร่หลายมากขึ้นว่านามแฝงสตริง'ดัชนี'และ'คอลัมน์'สามารถใช้แทนจำนวนเต็ม 0/1 ได้ นามแฝงมีความชัดเจนมากขึ้นและช่วยให้ฉันจำได้ว่าการคำนวณเกิดขึ้นได้อย่างไร นามแฝงสำหรับ 'ดัชนี' ก็คือ'แถว'

เมื่อaxis='index'ถูกใช้การคำนวณจะเกิดขึ้นในคอลัมน์ซึ่งทำให้สับสน แต่ฉันจำได้ว่ามันได้ผลลัพธ์ที่มีขนาดเท่ากับแถวอื่น

มาดูข้อมูลบนหน้าจอเพื่อดูว่าฉันกำลังพูดถึงอะไร:

df = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
          a         b         c         d
0  0.990730  0.567822  0.318174  0.122410
1  0.144962  0.718574  0.580569  0.582278
2  0.477151  0.907692  0.186276  0.342724
3  0.561043  0.122771  0.206819  0.904330
4  0.427413  0.186807  0.870504  0.878632
5  0.795392  0.658958  0.666026  0.262191
6  0.831404  0.011082  0.299811  0.906880
7  0.749729  0.564900  0.181627  0.211961
8  0.528308  0.394107  0.734904  0.961356
9  0.120508  0.656848  0.055749  0.290897

เมื่อเราต้องการหาค่าเฉลี่ยของคอลัมน์ทั้งหมดเราจะใช้axis='index'เพื่อรับสิ่งต่อไปนี้:

df.mean(axis='index')
a    0.562664
b    0.478956
c    0.410046
d    0.546366
dtype: float64

ผลลัพธ์เดียวกันจะได้รับจาก:

df.mean() # default is axis=0
df.mean(axis=0)
df.mean(axis='rows')

หากต้องการใช้การดำเนินการจากซ้ายไปขวาบนแถวให้ใช้แกน = 'คอลัมน์' ฉันจำได้โดยคิดว่าอาจมีการเพิ่มคอลัมน์เพิ่มเติมใน DataFrame ของฉัน:

df.mean(axis='columns')
0    0.499784
1    0.506596
2    0.478461
3    0.448741
4    0.590839
5    0.595642
6    0.512294
7    0.427054
8    0.654669
9    0.281000
dtype: float64

ผลลัพธ์เดียวกันจะได้รับจาก:

df.mean(axis=1)

เพิ่มแถวใหม่ด้วยแกน = 0 / ดัชนี / แถว

ลองใช้ผลลัพธ์เหล่านี้เพื่อเพิ่มแถวหรือคอลัมน์เพิ่มเติมเพื่อให้คำอธิบายสมบูรณ์ ดังนั้นเมื่อใดก็ตามที่ใช้แกน = 0 / ดัชนี / แถวก็เหมือนกับการได้รับแถวใหม่ของ DataFrame เพิ่มแถวกันเถอะ:

df.append(df.mean(axis='rows'), ignore_index=True)

           a         b         c         d
0   0.990730  0.567822  0.318174  0.122410
1   0.144962  0.718574  0.580569  0.582278
2   0.477151  0.907692  0.186276  0.342724
3   0.561043  0.122771  0.206819  0.904330
4   0.427413  0.186807  0.870504  0.878632
5   0.795392  0.658958  0.666026  0.262191
6   0.831404  0.011082  0.299811  0.906880
7   0.749729  0.564900  0.181627  0.211961
8   0.528308  0.394107  0.734904  0.961356
9   0.120508  0.656848  0.055749  0.290897
10  0.562664  0.478956  0.410046  0.546366

เพิ่มคอลัมน์ใหม่ด้วยแกน = 1 / คอลัมน์

ในทำนองเดียวกันเมื่อแกน = 1 / คอลัมน์จะสร้างข้อมูลที่สามารถสร้างเป็นคอลัมน์ของตัวเองได้อย่างง่ายดาย:

df.assign(e=df.mean(axis='columns'))

          a         b         c         d         e
0  0.990730  0.567822  0.318174  0.122410  0.499784
1  0.144962  0.718574  0.580569  0.582278  0.506596
2  0.477151  0.907692  0.186276  0.342724  0.478461
3  0.561043  0.122771  0.206819  0.904330  0.448741
4  0.427413  0.186807  0.870504  0.878632  0.590839
5  0.795392  0.658958  0.666026  0.262191  0.595642
6  0.831404  0.011082  0.299811  0.906880  0.512294
7  0.749729  0.564900  0.181627  0.211961  0.427054
8  0.528308  0.394107  0.734904  0.961356  0.654669
9  0.120508  0.656848  0.055749  0.290897  0.281000

ดูเหมือนว่าคุณจะเห็นนามแฝงทั้งหมดที่มีตัวแปรส่วนตัวต่อไปนี้:

df._AXIS_ALIASES
{'rows': 0}

df._AXIS_NUMBERS
{'columns': 1, 'index': 0}

df._AXIS_NAMES
{0: 'index', 1: 'columns'}

1

เมื่อแกน = 'แถว' หรือแกน = 0 หมายความว่าเข้าถึงองค์ประกอบในทิศทางของแถวขึ้นลง หากใช้ sum ตามแกน = 0 จะทำให้เรามีผลรวมของแต่ละคอลัมน์

เมื่อแกน = 'คอลัมน์' หรือแกน = 1 หมายถึงการเข้าถึงองค์ประกอบในทิศทางของคอลัมน์จากซ้ายไปขวา หากใช้ sum ตามแกน = 1 เราจะได้ผลรวมของแต่ละแถว

ยังงง! แต่ข้างต้นช่วยให้ฉันง่ายขึ้นเล็กน้อย


0

ฉันพบว่าคำตอบอื่น ๆ ทั้งหมดสับสน นี่คือวิธีที่ฉันคิดเกี่ยวกับเรื่องนี้:

axis=0: รูปร่างของผลลัพธ์เป็นแนวนอน (แถว)
axis=1: รูปร่างของผลลัพธ์เป็นแนวตั้ง (คอลัมน์)

ดังนั้น

  • df.drop(name, axis=1): วางคอลัมน์
  • df.mean(axis=1): คำนวณคอลัมน์ (สามารถเพิ่มผลลัพธ์เป็นคอลัมน์ใหม่ได้)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.