본문 바로가기
컴퓨터

파이썬 데이터프레임 다루기

by LightBlogger 2022. 3. 28.

오랜만에 사용하려고 하면 늘 헛갈리는 파이썬 데이터프레임 다루기.

 

사실 헛갈리는 이유는 동일한 결과를 낼 수 있는 방법이 너무 많기 때문이라고 생각한다.

 

개인적으로 가장 심플하다고 생각하는 방법 하나씩만 정리해 둔다.

 

 

1. 특정 열 인덱싱

 

df_temp = df.loc[:, ['a']]

 

df['a'] 같은 방식은 잊어버리자. 나중에 행 인덱싱할 때 꼭 df[0,] 같은 것도 동작할 것처럼 착각하게 된다.

그냥 인덱싱은 무조건 loc 사용한다고 생각하는 편이 맘 편하다.

[:] 은 all 의 의미.

열 이름을 굳이 리스트에 담아 전달하는 것은 익숙해질 때까지 다소 어색하지만 두 가지 이점이 있다.

1. 하나의 열만 인덱싱하더라도 결과가 데이터프레임으로 반환된다. (df.loc[:, 'a'] 의 결과는 판다스 시리즈로 반환된다.)

2. 콤마를 사용하면 여러 개의 열을 동시에 인덱싱할 수도 있다.

 

2. 특정 행 인덱싱

 

df_temp = df.loc[[0], :]

 

df['a'] 같은 방식은 잊어버리자(2)

그럼 그냥 열 인덱싱의 반대일 뿐이다.

행 이름을 굳이 리스트에 담아 전달하는 것은(...이하 생략)

 

3. 순서로 열이나 행 인덱싱

 

df_temp = df.iloc[:, [0]]

 

location 대신 integer location 을 사용한다는 것만 다르다

 

 

4. ~부터 ~까지 인덱싱

 

df_temp = df.iloc[0:4, :]

 

역시 integer location 을 사용하면 된다. 위는 첫 행부터 4개의 행을 인덱싱, 아래는 두 번째 열부터 5개의 열을 인덱싱

 

df_temp = df.iloc[:, 1:6]

 

범위 인덱싱은 범위 자체가 리스트이므로 당연히 결과가 판다스 데이터프레임으로 반환된다.

 

'마지막에서 몇 개 행'을 인덱싱하는 것은 위 예에 비해서는 직관적이지 않다. 아래는 마지막에서부터 60개 열을 인덱싱하는 예다.

 

df_temp = df.iloc[-60:, :]

 

 

5. 정렬

 

df_temp = df.sort_values('a', ascending=True)

 

 

혹시 특정 열이 아니라 index를 활용해 정렬하려면 다음과 같이

 df_temp = df.sort_index(ascending=False)

 

 

정렬 후에는 인덱스 초기화가 필요하다.

df_temp = df_temp.reset_index(drop=True)

 

 

6. 데이터프레임끼리 합치기

 

df_temp = padnas.concat([df1, df2], axis='rows')

 

df1, df2를 리스트로 전달해야 한다는 게 함정

위 예는 행 방향(아래)으로 합친다. 열 방향(옆)으로 합치려면 axis='columns' 만 바꾸면 된다.

행 방향으로 합친 후엔 역시 인덱스 초기화가 필요하다. (ignore_index=True 같은 옵션도 있으나 헛갈리므로 알아두지 말기로 하자)

 

 

7. 마지막 행에 개별 데이터 추가하기

 

df.loc[len(df), 'a'] = value

 

이게 제일 기억하기 쉽다. 근데 값을 추가하는 순간 len(df) 값이 달라지므로, 반복문 내에서 마지막 행 여러 열에 값을 추가해야 할 때는 반복문 처음에 last_row = len(df) 와 같이 값을 하나 고정해 놓고 last_row 행에 추가하는 방식이 좋다.

 

 

8. A열의 값이 1인 바로 그 행의 B열 값

 

df.loc[df.loc[:, 'a'] == 1, 'b']

 

'행' 부분에 df.loc[:, 'a'] == 1 을 적어주었을 뿐이다.

단일 데이터 인덱싱이므로 인수로 리스트를 사용하지 않는 df.loc[0, 'a'] 를 기본형으로 생각하자.

 

 

9. 특정 열 삭제

 

df = df.drop(['a', 'b'], axis='columns')

 

역시 삭제하고 싶은 열을 리스트로 전달해야 한다는 게 함정.

df = 을 사용하지 않는 df.drop(... inplace=True) 같은 것도 있으나 역시 모르기로 하자.

행은 columns 를 rows 로만 바꿔주면 된다.

 

10. 데이터프레임 마지막 행 구글시트에 추가하기

 

scope / json_file_name / credentials / gc 등의 선언이 완료되었다는 가정 하에

 

url = 'https://...'
doc = gc.open_by_url(url)
sheet = doc.worksheet('sheet_name')
sheet.append_row(df.iloc[-1, :].values.tolist(), table_range='A1')

 

iloc의 -1은 순서상 마지막을 의미

table_range 는 append하는 기준, 생략하면 이미 데이터가 있을 경우 빈 열에 붙인다거나 하는 오동작이 있다.

근데 가끔 df.iloc[-1, :].values.tolist() 부분에서 Object of type 'int64' is not JSON serializable 같은 에러가 날 때가 있다. 데이터프레임에서 쓰던 자료형이 호환이 안 된다는 얘기인데... 처리하는 세련된 방법이 당연히 있겠지만 따로 기억하기 귀찮으니 다음과 같이 다소 무식하게(?) 리스트를 생성해서 append_row()에 넣는 것도 방법이겠다.

 

temp_df = df.iloc[-1, :]
temp_list = []
for i in range(len(temp_df)):
	temp_list.append(float(temp_df[i]))

 

참고로 데이터 업데이트 전 구글시트 clear가 필요하다면 다음 코드를 사용. 이런 건 어쩔 수 없이 기억(록)해 둬야 한다.

 

sheet.batch_clear(['A1:B2'])
반응형

댓글