미식가의 개발 일기

[판다스] 데이터 프레임(DataFrame) 조작 본문

BigData

[판다스] 데이터 프레임(DataFrame) 조작

대체불가 핫걸 2024. 7. 12. 14:48

 

데이터 프레임 생성

import pandas as pd

data = {
    '이름': ['바둑이', '나비', '호랑이'],
    '나이': [5, 3, 10],
}

df = pd.DataFrame(data)
df.index = [1, 2, 3]
df

 

특정 열 선택, 추가, 삭제, 변경

열 선택
  • 요소가 하나일 때
age = df['나이']
age

 

  • 요소가 2개 이상일 때 -> 리스트로 요소 전달
age = df[['이름','나이']]
age

 

열 추가
  • 취미라는 열 추가
hobby = ['먹기', '자기', '놀기']
df['취미'] = hobby
df

 

열 삭제
  • del
del df['취미']

 

  • drop
df.drop(columns=['취미'])

 

열 이름 변경
columns = {'이름': 'name', '나이': 'age'}

df.rename(columns=columns, inplace=True)
df

※ 주의할 점※

만약 열 이름을 변경한 값을 새로운 데이터 프레임으로 생성하려면 inplce=True를 지워줘야 한다. inplce=True는 데이터 프레임을 직접 수정하는 것이고 데이터 프레임을 반환하지는 않으므로 새로운 변수에 할당해주면 그 변수는 None값을 가진다.

따라서 새로운 열 이름이 변경된 새로운 데이터 프레임을 생성하고 싶다면 아래처럼 inplace를 제거하고 써주면 된다.

columns = {'이름': 'name', '나이': 'age'}

res_df = df.rename(columns=columns)
res_df

 

인덱싱(Indexing)

-> 슬라이싱도 가능

 

라벨 기반(loc)

df.loc[행, 원하는 열의 이름]
  • 첫 번째 행
first = df.loc[1]
first

 

  • 두 번째 행의 이름 컬럼
name = df.loc[2, '이름']
name

 

  • 나이가 5 이상인 이름 컬럼
name = df.loc[df['나이'] >= 5, '이름']
name

 

정수 기반(iloc)

df.iloc[행, 열의 순서]
  • 두 번째 행까지의 첫 번째 열
# iloc[행 범위, 열 범위]
res = df.iloc[0:2,0]
res

 

 

  • 두 번째 행의 전체 데이터
res = df.iloc[1, :]
res

 

  • 첫 번째 행의 첫 번째, 세 번째 데이터
res = df.iloc[0, [0, 2]]
res

 

필터링(filtering) -> isin, str.contains, &, |, ~

  • 나이가 5 이상인 값을 추출
age = df[df['나이'] >= 5]
age

 

  • 이름이 바둑이, 호랑이인 행 추출
name = df[df['이름'].isin(['바둑이', '호랑이'])]
name

 

  • 이름이 바둑이, 호랑이인 행의 나이 10씩 올리기
df.loc[df['이름'].isin(['바둑이', '호랑이']), '나이'] += 10

 

  • 이름에 '이'가 들어가는 행 추출
filtered = df[df['이름'].str.contains('이')]
# filtered = df[~df['이름'].str.contains('이')] 이름에 '이'가 들어가지 않는 행 추출
filtered

 

  • 이름에 '이'가 들어가면서 나이가 10인 행 추출

   -> and: &, or: |, not: ~

nameage = df[(df['이름'].str.contains('이')) & (df['나이'] == 10)]
nameage

 

 

 

구간 분류(cut)

  • 나이가 5보다 작으면 Baby, 크거나 같으면 Adult로 분류
df['나이'] = pd.cut(df['나이'], 
                  bins = [0, 5, 15], 
                  labels = ['Baby', 'Adult'],
                  right=True) # 각 구간의 최댓값 포함

 

 

  • 구간별 데이터를 균등하게 분할하고 싶다면 qcut 사용
df['나이'] = pd.qcut(df['나이'], 
                  q = 3, 
                  labels = ['A', 'B', 'C'],)

 

교체(replace)

df['나이'] = df['나이'].replace({'A': 3, 'B': 5, 'C': 10})

 

정렬(sort)

  •  특정 값 기준 정렬
sorted_df = df.sort_values(by='나이')
# 내림차순 정렬은 ()안에 ascending=False 추가
# sorted_df = df.sort_values(by='나이', ascending=False)
sorted_df

 

인덱스 재설정(reset_index)

df = sorted_df.reset_index(drop=True)
# 기존 인덱스를 남겨 놓으려면 drop=False 지정
df

 

변환(apply)

  • 나이가 5 미만이면 baby, 아니면 adult를 가지는 연령 컬럼 추가
def age(age):
    if age < 5:
        return 'baby'
    else:
        return 'adult'

result_df['연령'] = df['나이'].apply(age)
result_df

 

  • 람다 함수 사용
# axis=1은 행에 따라 적용, axis=0은 열에 따라 적용
df['연령'] = df.apply(lambda x: 'baby' if x['나이'] < 5 else 'adult', axis=1)

 

  • 나이를 10씩 올리기
df = pd.DataFrame(data)
df['나이'] = df['나이'].apply(lambda x: x+10)
df

 

시리즈 객체 대상 변환(map)

df['나이'] = df['나이'].map({'A': 3, 'B': 5, 'C': 10})

mapping = {'A': 3, 'B': 5, 'C': 10}
df['나이'] = df['나이'].map(lambda x: mapping.get(x, x))

 

모든 원소 대상 변환(applymap)

  • 모든 원소에 대해 문자열 변환 -> 시리즈에서는 사용 X
df.applymap(lambda x: str(x))

 

 

for문으로 요소 탐색

for index, row in df.iterrows():
    print(f"인덱스: {index}")
    print(f"이름: {row['이름']}, 나이: {row['나이']}")
인덱스: 1
이름: 바둑이, 나이: 5
인덱스: 2
이름: 나비, 나이: 3
인덱스: 3
이름: 호랑이, 나이: 10

 

그룹별 연산(groupby)

# 학과 별로 묶어서 나이의 평균을 구할 때
df.groupby('학과')['나이'].mean()

-> 그룹으로 묶을 원소가 2개 이상이라면 리스트로 감싸줘야 함( df.groupby(['v1', 'v2']) )

 

  • 각 행별로 그룹별 연산한 값 채우기
# 학과 별로 묶어서 각 학과별 나이의 평균을 값에 대입
df.groupby('학과')['나이'].transform('mean')

 

컬럼 별 빈도 확인(count_values)

df['이름'].value_counts()
이름
바둑이    1
나비     1
호랑이    1
Name: count, dtype: int64

 

  • 빈도 비율 확인
df['이름'].value_counts(normalize=True)
이름
바둑이    0.333333
나비     0.333333
호랑이    0.333333
Name: proportion, dtype: float64

 

 

데이터 프레임 늘리기(pd.melt)

데이터 프레임을 넓은 형식에서 긴 형식으로 늘릴 때 사용
  • 이런 형태의 데이터 프레임에서 남자와 여자를 하나의 열로 합치고 싶다면?

df_melted = pd.melt(df, id_vars=['학과'], value_vars=['남자', '여자'], var_name='성별', value_name='인구수')
df_melted

반응형