03wk-2: Pandas – 행과 열의 선택

pandas
Author

최규빈

Published

September 20, 2023

1. 강의영상

2. Imports

import numpy as np
import pandas as pd

3. Pandas: 행과 열의 선택

- 두 가지 형태의 데이터프레임

dct = {'date': ['12/30','12/31','01/01','01/02','01/03'], 'X1': [65,95,65,55,80], 'X2': [55,100,90,80,30], 'X3': [50,50,60,75,30], 'X4': [40,80,30,80,100]}
df = pd.DataFrame(dct) 
df
date X1 X2 X3 X4
0 12/30 65 55 50 40
1 12/31 95 100 50 80
2 01/01 65 90 60 30
3 01/02 55 80 75 80
4 01/03 80 30 30 100
ts = pd.DataFrame({'X1': [65,95,65,55,80], 'X2': [55,100,90,80,30], 'X3': [50,50,60,75,30], 'X4': [40,80,30,80,100]}, index=['12/30','12/31','01/01','01/02','01/03']) 
ts
X1 X2 X3 X4
12/30 65 55 50 40
12/31 95 100 50 80
01/01 65 90 60 30
01/02 55 80 75 80
01/03 80 30 30 100

A. 열의 선택

- 방법1: df.? + str

# df.X1

- 방법2: df[?] + str, [str,str]

# df['X1'] # str 
# df[['X1']] # [str]
# df[['X1','X3']] # [str,str]

- 방법3: df.iloc[:,?] + int, int:int, [int,int], [bool,bool], range

# df.iloc[:,0] # int
# df.iloc[:,-2:] # int:int - 슬라이싱
# df.iloc[:,1::2] # int:int - 스트라이딩
# df.iloc[:,[0]] # [int]
# df.iloc[:,[0,1]] # [int,int]
# df.iloc[:,[True,True,False,False]] # bool의 list 
# df.iloc[:,range(2)] # range

- 방법4: df.loc[:,?] + str, ‘str:str’, [str,str], [bool,bool]

# df.loc[:,'X1'] # str
# df.loc[:,'X1':'X3'] # 'str':'str' -- 칼럼이름으로 슬라이싱 **
# df.loc[:,'X1'::2] # 'str':'str' -- 칼럼이름으로 스트라이딩 ** 
# df.loc[:,['X1']] # [str]
# df.loc[:,['X1','X4']] # [str,str]
# df.loc[:,[True,False,False,True]] # bool의 list

B. 행의 선택

- 방법1: df[] + int:int, str:str, [bool,bool], pd.Series([bool,bool]) – \((\star\star\star\star\star)\)

# df[:2] # int:int -- 슬라이싱 // df.iloc[:2,:], df.iloc[:2] 와 같음
# df[::2] # int:int -- 스트라이딩 
# ts['12/30':'01/02'] # str:str -- 슬라이싱
# ts['12/31'::2] # str:str -- 스트라이딩
# df[['12' in date for date in df.date]] # [bool,bool]
# df[df.X1 < 70] # pd.Series([bool,bool])

- 방법2: df.iloc[], df.iloc[,:] + int, int:int, [int,int], [bool,bool], range

# df.iloc[0] # int 
# df.iloc[-2:] # int:int -- 슬라이싱
# df.iloc[1::2] # int:int -- 스트라이딩
# df.iloc[[0]] # [int]
# df.iloc[[0,1]] # [int,int]
# df.iloc[['12' in date for date in df.date]] # [bool,bool]
# df.iloc[range(2)] # range
# df.iloc[0,:] # int 
# df.iloc[-2:,:] # int:int -- 슬라이싱
# df.iloc[1::2,:] # int:int -- 스트라이딩
# df.iloc[[0],:] # [int]
# df.iloc[[0,1],:] # [int,int]
# df.iloc[['12' in date for date in df.date],:] # [bool,bool]
# df.iloc[range(2),:] # range

- 방법3: df.loc[], df.loc[,:] + int, str, int:int, str:str, [int,int], [str,str], [bool,bool], pd.Series([bool,bool])

# df.loc[0] # int 
# ts.loc['12/30'] # str 
# df.loc[:2] # int:int 
# ts.loc[:'01/02'] # str:str 
# df.loc[[0,1]] # [int,int]
# ts.loc[['12/30','01/01']] # [str,str]
# df.loc[['12' in date for date in df.date]] # [bool,bool]
# df.loc[df.X1>70] # pd.Series([bool,bool]) 

D. 제 스타일

- 가장 안전한 코드

# df.loc[:,:]

- 상황1: 하나의 col을 뽑으려 할때 좋은 코드

# df.X1 # 최애 
# df['X1'] # 차애 
# df[['X1']] # 차애

- 상황2: row 슬라이싱을 할때 좋은 코드 \((\star\star\star)\)

# df[:5] # 최애 
# ts[:'01/02'] # 시계열인 경우 

- 상황3: 조건에 맞는 row를 뽑을때 좋은 코드

# df[df.X1<60] # 최애
# df.loc[['12' in date for date in df.date]] # 차애

- 상황4: 하나의 row를 뽑으려 할때 좋은 코드

# df.iloc[0] # 최애 
# df.loc[0] # 차애

- 상황5: (row,col)을 뽑으려 할때 좋은 코드

# 최애: pd.Series를 뽑고 -> 인덱스로접근
# df.X1[0]
# df['X1'][0]

# 차애: iloc, loc 으로 한번에 뽑기
# df.iloc[0,0]
# df.loc[0,'X1']

위의 상황이외에는 df.loc[:,:]를 사용하는것이 유리하다

- 상황6: column 슬라이싱을 할때

# df.loc[:,'X1':'X3'] # 끝점포함

- 상황7: row + column 슬라이싱을 하는 가장 좋은 코드

df.loc[::2,'X1':'X2']
X1 X2
0 65 55
2 65 90
4 80 30

- 상황8: 조건에 맞는 col을 뽑기에 가장 좋은 코드

# df.loc[:,[len(colname)>2 for colname in df.columns]]

- 상황9: 조건에 맞는 row, col을 뽑기에 가장 좋은 코드

# df.loc[df.X1>70,[len(colname)>2 for colname in df.columns]]

D. 제 스타일 X

- 제가 안쓰는 코드1

df[:1]
date X1 X2 X3 X4
0 12/30 65 55 50 40

이러면 내 입장에서는 마치 아래가 동작할 것 같잖아..

df[0] 
KeyError: 0

- 제가 안쓰는 코드2: bool의 list를 사용할때 iloc은 가급적 쓰지마세요

df.iloc[list(df['X1']<80),:]
date X1 X2 X3 X4
0 12/30 65 55 50 40
2 01/01 65 90 60 30
3 01/02 55 80 75 80

이러면 마치 아래도 동작할 것 같잖아..

df.iloc[df['X1']<80,:]
NotImplementedError: iLocation based boolean indexing on an integer type is not available

E. 요약

- 알아두면 좋은 규칙

  • .iloc[].iloc[,:]는 완전히 동등하다.
  • .loc[].loc[,:]는 완전히 동등하다.
  • 결과를 pd.Series 형태가 아닌 pd.DataFrame 형태로 얻고 싶다면 [[?]]를 사용하면 된다.

- 정리

type of indexer . [] .iloc .loc 내가 쓴다면?
int X X O \(\Delta\) df.iloc[3,:]
int:int X O O \(\Delta\) df[3:5]
[int,int] X X O \(\Delta\) df.iloc[idx,:]
str X X X O ts.loc['time1',:]
str:str X O X O ts.loc['time1':'time2',:]
[str,str] X X X O 안할 듯
[bool,bool] X O O O df[filtered_idx]
pd.Series([bool,bool]) X O X O df[df.X1>20]
type of indexer . [] .iloc .loc 내가 쓴다면?
int X X O X df.iloc[:,0]
int:int X X O X df.iloc[:,0:2]
[int,int] X X O X df.iloc[:,idx]
str O O X O df.loc[:,'X1']
str:str X X X O df.loc[:,'X1':'X4']
[str,str] X O X O df.loc[:,colname_list]
[bool,bool] X X O O df.loc[:,bool_list]

4. HW

아래와 같은 데이터프레임이 있다고 하자.

df=pd.read_csv('https://raw.githubusercontent.com/PacktPublishing/Pandas-Cookbook/master/data/movie.csv')
df
color director_name num_critic_for_reviews duration director_facebook_likes actor_3_facebook_likes actor_2_name actor_1_facebook_likes gross genres ... num_user_for_reviews language country content_rating budget title_year actor_2_facebook_likes imdb_score aspect_ratio movie_facebook_likes
0 Color James Cameron 723.0 178.0 0.0 855.0 Joel David Moore 1000.0 760505847.0 Action|Adventure|Fantasy|Sci-Fi ... 3054.0 English USA PG-13 237000000.0 2009.0 936.0 7.9 1.78 33000
1 Color Gore Verbinski 302.0 169.0 563.0 1000.0 Orlando Bloom 40000.0 309404152.0 Action|Adventure|Fantasy ... 1238.0 English USA PG-13 300000000.0 2007.0 5000.0 7.1 2.35 0
2 Color Sam Mendes 602.0 148.0 0.0 161.0 Rory Kinnear 11000.0 200074175.0 Action|Adventure|Thriller ... 994.0 English UK PG-13 245000000.0 2015.0 393.0 6.8 2.35 85000
3 Color Christopher Nolan 813.0 164.0 22000.0 23000.0 Christian Bale 27000.0 448130642.0 Action|Thriller ... 2701.0 English USA PG-13 250000000.0 2012.0 23000.0 8.5 2.35 164000
4 NaN Doug Walker NaN NaN 131.0 NaN Rob Walker 131.0 NaN Documentary ... NaN NaN NaN NaN NaN NaN 12.0 7.1 NaN 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
4911 Color Scott Smith 1.0 87.0 2.0 318.0 Daphne Zuniga 637.0 NaN Comedy|Drama ... 6.0 English Canada NaN NaN 2013.0 470.0 7.7 NaN 84
4912 Color NaN 43.0 43.0 NaN 319.0 Valorie Curry 841.0 NaN Crime|Drama|Mystery|Thriller ... 359.0 English USA TV-14 NaN NaN 593.0 7.5 16.00 32000
4913 Color Benjamin Roberds 13.0 76.0 0.0 0.0 Maxwell Moody 0.0 NaN Drama|Horror|Thriller ... 3.0 English USA NaN 1400.0 2013.0 0.0 6.3 NaN 16
4914 Color Daniel Hsia 14.0 100.0 0.0 489.0 Daniel Henney 946.0 10443.0 Comedy|Drama|Romance ... 9.0 English USA PG-13 NaN 2012.0 719.0 6.3 2.35 660
4915 Color Jon Gunn 43.0 90.0 16.0 16.0 Brian Herzlinger 86.0 85222.0 Documentary ... 84.0 English USA PG 1100.0 2004.0 23.0 6.6 1.85 456

4916 rows × 28 columns

이 데이터프레임의 columns은 아래와 같다.

df.columns
Index(['color', 'director_name', 'num_critic_for_reviews', 'duration',
       'director_facebook_likes', 'actor_3_facebook_likes', 'actor_2_name',
       'actor_1_facebook_likes', 'gross', 'genres', 'actor_1_name',
       'movie_title', 'num_voted_users', 'cast_total_facebook_likes',
       'actor_3_name', 'facenumber_in_poster', 'plot_keywords',
       'movie_imdb_link', 'num_user_for_reviews', 'language', 'country',
       'content_rating', 'budget', 'title_year', 'actor_2_facebook_likes',
       'imdb_score', 'aspect_ratio', 'movie_facebook_likes'],
      dtype='object')

actor 라는 단어가 포함된 column만을 선택하는 코드를 작성하라.

# 출력결과는 아래와 같다. 
actor_3_facebook_likes actor_2_name actor_1_facebook_likes actor_1_name actor_3_name actor_2_facebook_likes
0 855.0 Joel David Moore 1000.0 CCH Pounder Wes Studi 936.0
1 1000.0 Orlando Bloom 40000.0 Johnny Depp Jack Davenport 5000.0
2 161.0 Rory Kinnear 11000.0 Christoph Waltz Stephanie Sigman 393.0
3 23000.0 Christian Bale 27000.0 Tom Hardy Joseph Gordon-Levitt 23000.0
4 NaN Rob Walker 131.0 Doug Walker NaN 12.0
... ... ... ... ... ... ...
4911 318.0 Daphne Zuniga 637.0 Eric Mabius Crystal Lowe 470.0
4912 319.0 Valorie Curry 841.0 Natalie Zea Sam Underwood 593.0
4913 0.0 Maxwell Moody 0.0 Eva Boehnke David Chandler 0.0
4914 489.0 Daniel Henney 946.0 Alan Ruck Eliza Coupe 719.0
4915 16.0 Brian Herzlinger 86.0 John August Jon Gunn 23.0

4916 rows × 6 columns


hint: 아래는 column 이름이 5글자 이하인 열을 출력하는 코드를 작성한 것이다.

df.loc[:,[len(col_name)<=5 for col_name in df.columns]]
color gross
0 Color 760505847.0
1 Color 309404152.0
2 Color 200074175.0
3 Color 448130642.0
4 NaN NaN
... ... ...
4911 Color NaN
4912 Color NaN
4913 Color NaN
4914 Color 10443.0
4915 Color 85222.0

4916 rows × 2 columns

note: [len(col_name)<=5 for col_name in df.columns] 와 같은 컴프리헨션 문법이 익숙하지 않다면

의 리스트컴프리헨션을 복습할 것