class="layout-aside-right paging-number">
본문 바로가기
데이터 분석/Python

pandas : Merge, join, concat, append , lamda, split, rrule

by heestory323 2025. 3. 18.

● pandas 와 numpy 모듈로 불러오기

import pandas as pd

import numpy as np 

 

● google colab에서 내 드라이브와 동기화 하는 법

from google.colab import drive
drive mount('/content/drive)

 

#csv파일 불러오기 

df = pd.read_csv("경로")

 

테이블 구조 파악

#데이터 얼마나 들어있나 count
len(df)

 

"테이블 열과 행 갯수",df.shape
"데이터 첫 5줄 확인 " , df.head()
"테이블 컬럼 타입",df.dtypes
"테이블 내 컬럼 확인", df.columns
   -테이블 컬럼을 list화  df.columns.to_list()
"테이블 행 상세확인", df.values

 

#가로/세로형 바꾸기(테이블 행렬전환) 
df.T
# 전체 행 갯수, 평균, 표준편차, 최솟값, 사분위수, 최댓값 확인
df2.describe()

 

결측치(null) 찾기

SQL 문에서 select count(*) from 테이블명

where 컬럼 is null    -> 과 동일한 조건 적용

df.isna().sum()
df.isnull().sum()
# 특정컬럼 지정하기    -> 대소문자 완전 똑같이 !!!!!!! 
df['Category']
df['user id']
# 특정컬럼을 여러개 지정 [ [ ] ]
# df [ ['category1','category2'] ]
df[['user id','product id']]
# 컬럼 삭제하기
index를 drop하려면 axis=0 , 컬럼을 drop하려면 axls=1 
df3 = df3.drop(['Brand Name'],axis=1)
df3
 
#결측치 삭제하기
결측치 dropna
df = df.dropna (axis=0, how='any', thresh=None, subset=None, inplace=False)

axis : {0: index / 1: columns} 

how : {'any' : 존재하면 제거 / 'all' : 모두 결측치면 제거}

 

조건 지정

# where -- 조건에 만족하는 행 - 정상출력, 나머지 - NaN
df2.where(df2['Age']>50)

# mask = (  ()  & ()  ) -- 조건1 & 조건2 에 부합하는 데이터만 가져오기
mask = ( (df2['Age']>20) & (df2['Gender']=='Male') )
df2[mask]

#데이터프레임명[조건] -- 조건을 만족하는 행만 필터링
df2 = df2[df2['Age']>50]
df2

# .loc[조건]
df2 = df2.loc[df2['Age']>50]
df2

 

group그룹핑하기

# 데이터프레임.groupby(기준컬럼)집계함수할컬럼.집계함수  -- 기준 1개
df2.groupby('Gender')['Customer ID'].count()
# 데이터프레임.groupby(기준컬럼1,기준컬럼2)[집계함수할컬럼].집계함수 -- 기준n개 이상
df2.groupby( [ 'Gender','Location' ] )['Customer ID'].count()

 

중복제거 distinct

#unique/nunique 고유한 종류만 출력, 중복 제거
df2.groupby('Location')['Age'].unique() ##'Korea' 'Japan' .... 
df2.groupby('Location')['Age'].nunique() #64   == .count() 에 distinct 고유한 종류의 개수

 

정렬 order by

# .sort_values(ascending=False)   True 오름차순, False 내림차순
df2.groupby('Location')['Age'].nunique().sort_values(ascending=False)
 

 

# pandas 라이브러리를 활용한 csv 파일 읽기 
df = pd.read_csv("xxxx.csv")

# 테이블 확인하기 
display(df, df2, df3)

# 처음 5 줄만 출력하기 
#df2.head()

# 마지막 5 줄만 출력하기 
#df2.tail()

# 각 테이블의 행(가로) 길이 파악하기
len(df)

# shape: 테이블의 행과 열의 갯수를 반환 
df.shape

# dtypes: 테이블 내 컬럼타입(문자형, 숫자형, 배열 등) 확인
df.dtypes

# columns: 테이블 내 컬럼 확인
df.columns

# values: 테이블 내 각 행들을 배열 형태로 확인
df.values

# 테이블 기본 구조 한눈에 확인하기
df.info()

# 전체 행 갯수, 평균, 표준편차, 최솟값, 사분위수, 최댓값 확인 
df2.describe()

#컬럼별로 결측치(데이터가 없는) 확인하기 
df.isnull().sum()

# 특정 컬럼 1개 가져오기
	#방법1: 속성. 사용
	df.Category
	
	#방법2: [] 연산자 사용
	df['Category']
	
	#방법3: iloc 사용
	# : 은 모든 행을 가져오겠다는 의미이며 dataframe 의 인덱스 번호 4번(카테고리)컬럼을 가져오겠다는 희미
	df.iloc[:,4]

# 특정 컬럼 여러개 가져오기 
	#방법1: [[]] 연산자 사용
	# []를 하나 사용하면 결과값이 series 형태로 반환되어 key error 가발생되며, [[]] 는 dataframe 으로 반환되어 에러가 나지 않습니다. 
	df[['Category','Selling Price']]
	
	#방법2: iloc 사용
	# : 은 모든 행을 가져오겠다는 의미이며 dataframe 의 인덱스 번호 4번,7번 컬럼을 가져오겠다는 희미
	df.iloc[:,[4,7]]
	
# 특정 컬럼 버리기
# axis=0 은 인덱스 기준, 1은 컬럼 기준 삭제를 의미 
# inplace=True 는 원본을 변경하겠다는 의미, False 의 경우 원본테이블은 변경되지 않음
df3.drop('Interaction type', axis=1, inplace=True)

# 조건에 부합하는 데이터 가져오기1
# 조건에 만족하는 행은 정상출력 ,아닌 행은 NaN 으로 반환 
df2.where(df2['Age']>50)

# 조건에 부합하는 데이터 가져오기2
# true, false의 개념이 아닌 조건에 부합하는 데이터만 슬라이싱하여 가져오고 싶을 때 
# mask 메서드로 불립니다. 이름은 반드시 mask 일 필요가 없습니다. 
mask = ((df2['Age']>50) & (df2['Gender']=='Male'))
df2[mask]

# 조건에 부합하는 데이터 가져오기3
# 데이터프레임명[조건] 을 사용하면 조건을 만족하는 행만 필터링됩니다.
df2 = df2[df2['Age']>50] 

# 조건에 부합하는 데이터 가져오기4
# loc[]을 활용한 조건 필터링
df2 = df2.loc[df2['Age']>50]

# 데이터 그루핑- 기준 1개
df2.groupby('Gender')['Customer ID'].count()

# 데이터 그루핑- 기준 여러개
df2.groupby(['Gender','Location'])['Customer ID'].count()

# 데이터 count 와 nunique(distinct, 중복제거) 차이 
df2.groupby('Location')['Age'].count()
df2.groupby('Location')['Age'].nunique()

 

 

Python 데이터 결합 

Merge 

공통 컬럼(가로, key)을 기준으로 테이블 병합 (SQL JOIN과 비슷)

# 컬럼명이 같은 경우의 예시를 보여주기 위해 컬럼명을 임의로 변경해 줌
df3['Customer ID']=df3['user id']

# 기본 작성구문으로, 디폴트 inner join
# 공통컬럼값은 합쳐져 하나의 컬럼으로 출력

merge_df = pd.merge(df2,df3)
merge_df = pd.merge(df2,df3, how='inner', on=' 공통컬럼이름' )

  • 주요옵션(파라미터)
    • on: 조건 컬럼이 한개인지 여러개인지 (어떤 컬럼을 기준으로 합칠건지)
    • how: 어떤 조인 방식을 사용할 것인지 (inner, outer, left, right)
    • left on / right on : 열기준 병합 시 기준으로 할 열의 양측 이름이 다르다면, 각각 어떤 열을 기준으로 할 지 지정합니다.
    • sort: 병합 후 인덱스 정렬 여부(True/False)
    • suffixes: 중복된 컬럼 이름의 처리 ( _left / _right )
    • indicator: True 로 할 경우, 마지막 열에 병합 정보를 출력해줍니다.

 

                                  # 공통컬럼 이름이 다를 시 left_on = ' ' , right_on = ' ' 으로 지정

# 공통컬럼이 2개 이상일 때
merge_df = pd.merge(df2, df3, how='inner', on=['공통컬럼1','공통컬럼2'])

# 기준열 이름이 다를 때
merge_df = pd.merge(df2,df3, how='inner', left_on = 'Customer ID', right_on = 'user id')

 

# suffixes = ( '_left' ,  '_right' )

merge() 로 합쳤는데, 각 테이블에 또 중복된 컬럼이 존재할경우 기본  _left   , _right  으로 구분가능.

 

📌 merge 결합 후 체크 또 체크 !  데이터 분석가들은 이걸 서로 체크해줘야하니까 코드도 자세하게 작성 !! 
# 컬럼 이름이 같을 때
merge_df = pd.merge(df2,df3,  how="inner", on="Customer ID")

# 컬럼 이름이 다를 때
merge_df = pd.merge(df2,df3, how="inner", left_on = 'Customer ID', right_on='user id')

이렇게 merge_df로 결합을 해 준 후
1. .shape 을 통해 테이블의 (행, 열) 갯수를 각각 체크하고
2. inner join이니까 결합한 테이블 merge_df의 갯수는 3294보다 작아야함
3. merge_df.shape 로 그게 맞는지 체크 
 - 컬럼이름이 다른 경우에는 컬럼(열)이 하나 늘어나니까 24

 

 

 

Join

인덱스(세로) 기준으로 테이블 병합. 

on 없이 사용시 왼쪽 데이터(left_df) 기준으로 오른쪽 데이터(right_df)를 붙이게 됨

on 사용시 특정열 기준으로 합치는 것도 가능 -> merge와 같은 기능

  • 주요옵션
    • how: 어떤 조인 방식을 사용할 것인지 (inner, outer, left, right)
    • lsuffix / rsuffix: 이름이 같은 컬럼이 있을 경우, 문자열 지정하여 부여
    • sort: 인덱스 정렬여부(True / False)

# 기본 구문

df.join(공통인덱스, how = 'right' )

# join시 이름이 같은 컬럼이 있을 경우, 옵션으로 설정하여 조인 가능
# 아래 코드는 오류가 남
# df.join(df2)
df.join(df2,how='left', lsuffix='1', rsuffix='2')

# join 이후, 인덱스 정렬하기
df.join(df2,how='left', lsuffix='1', rsuffix='2', sort=True)

 

Concat ****

2개 이상의 데이터프레임을 특정 축을 따라 연결하는데 사용됨.

# 기본 작성구문 :

   pd.concat([df2, df3])

 

# 디폴트 : 수직결합(위아래) 

# axis=0: 수직 /  axis=1: 수평

# ignore_index=True : 인덱스 재배열

# join = 'inner' : null값(NaN) 을 제외한 교집합

 

 

# 수직결합, union

pd.concat( [df2, df3], axis=0, ignore_index=True, join='inner' )

# 수평결합, merge

pd.concat( [df2, df3], axis=1, ignore_index=True, join='inner' )

  • 주요옵션
    • axis: 수직결합인지, 수평결합인지(axis=0: 수직결합(기본값) / axis=1: 수평결합)
    • join: 어떤 조인 방식을 사용할 것인지 (inner, outer, left, right)
    • join_axes : 조인 축 지정
    • keys: 데이터프레임 축이름 지정
    • ignore_index=True : 인덱스 재배열

concat 검증 가능

 

append

2개의 데이터 프레임을 행 기준으로 결합

  • 주요옵션
    • ignore_index: 기존 인덱스를 사용할지 여부. False로 할 경우 0,1,2,..,n 이 부여
    • sort : 열을 사전적으로 정렬할 지 여부

# df.append(df2)

 

Pivot Table : 내맘대로 테이블을 보고 싶을 때 사용

데이터의 열을 기준으로 피벗테이블로 변환시키는 함수

내가 원하는 컬럼들로 새로운 데이터프레임을 만들고, 계산까지 가능

 

pd.pivot_table(지정df, index = '    ', columns = '    ', values = '    ', aggfunc = '   ' )


# age 라는 축을 기준으로 카테고리별 고객id 카운트 
pd.pivot_table(df2, index='Age', columns='Category', values='Customer ID', aggfunc='count')

# age, Category 라는 축을 기준으로 성별 Previous Purchases 최소, 최대값 구하기 
pd.pivot_table(df2, index=['Age','Category'],columns='Gender', values='Previous Purchases', aggfunc=['min','max'])

# 성별을 축으로 하고, 사이즈, 나이별 고객id 고유하게 카운트 
pd.pivot_table(df2, index=['Gender'],columns=['Size','Age'], values='Customer ID', aggfunc='nunique')

 

  • 주요 옵션
    • index: 인덱스(축) 으로 사용될 열
    • columns: 열로 사용될 열
    • values: 값으로 사용될 열
    • ⭐ index 및 columns에 리스트 입력시  → 멀티 인덱스 기반 피벗테이블이 생성
            : 2개 이상의 인덱스로 데이터를 그룹화 / 세로(행) - 기준이 여러개인 채로 데이터 판별
    • ⭐ values 에 리스트를 입력 할 경우 → 피벗테이블이 옆쪽으로 연속으로 생성
           : 여러 값 한 번에  보기 / 기준은 하나인데 보고싶은 데이터 숫자가 여러개일때 
    • aggfunc: 어떠한 계산을 할 지    aggfunc = '집계함수 코드'
      • 합계  sum
      • 평균  mean
      • 중앙값 median
      • 표준편차  std
      • 갯수   count
      • 중복없이 갯수세기  nunique
      • 최대값   max
      • 최소값   min
      • fill_value: NaN 값을 처리하고 싶을 때 사용, fill_value=0 이 가장 많이 사용됨
      • dropna: 결측치(na)삭제 여부 결정 - 빈 값 있으면 자동 탈락
      • sort: index or columns 기준으로 정렬


 

  •  

lamda

이름 없는 함수, 함수를 한 번만 사용하거나 함수를 인자로 전달해야하는 경우 

똑같은 걸 간단히 표현할때

lamda 매개변수 : 표현식(인자)

# lambda 함수를 이용한 홀수 출력하기 
mylist = [1, 2, 3, 4, 5]

mylist2 = list(filter(lambda x: x % 2 == 1, mylist))
print(mylist2)

# lambda 함수를 이용한 정렬
mylist = ['apple', 'banana', 'cherry']
mylist2 = sorted(mylist, key=lambda x: len(x))
print(mylist2)

 

split

하나의 값으로 묶여있는 데이터를 문자열 기준으로 나눌때 사용,
특정 문자나 패턴으로 나눌 수 있음.

문자열.split(' ')

문자열.split(sep='구분자', maxsplit=분할 횟수)

문자열.split()[ ] 로 [ ] 위치에 있는 단일 문자열만 빼오는 거 가능 -> x.split('.')[i]

  • 주요 옵션
    • sep: 문자열을 나눌 구분자 기입, sep 생략 가능  
    • maxsplit: 최대 split 횟수 (디폴트: 모두 다 나눔)    문자열.split(sep='구분자', maxsplit=분할 횟수)
# 예시 문자열 선언 
s = "aa.bb.cc.dd.ee.ff.gg"

# '.' 구분자를 기준으로 데이터를 나눔 
# 아래 두 코드 결과 동일 
s.split('.')
s.split(sep='.')

# df 에 x 컬럼추가
df2['x']="aa.bb.cc.dd.ee.ff.gg"

 

#응용 #중요

# '.' 구분자를 기준으로 데이터를 나누고 컬럼으로 받음 
# lambda 함수와 결합하여 사용하는 경우 

# 데이터 프레임의 특정 컬럼에 대해 일괄적으로 변경을 위한 apply 함수 호출
# 7번 반복, a 를 컬럼 구분자로 받아주고, format 함수를 통해 a0, a1, a2 ... 로 표기
# lambda 함수를 통해 '.' 로 구분. 단, len(x.split('.') 즉 7 보다 i 가 작을 때 수행

for i in range(7):
         df2["a{}".format(i)] = df['x'].apply(lambda x: x.split('.')[6] if len(x.split('.')) > i else None)

 

inline if

결과값(조건만족할때) if 조건 조건안만족할때 

 

1. for 문으로 반복문 작성 for i in range(7):   -- 7번 반복하니까

2. 새로운 컬럼명을 a0, a1~~~~  형태로 생성 df[ "{새로운이름}".format(i) ] -- .format() 함수

3. apply() 와 lamba로 컬럼값 변환

4. .split('.') 으로 문자열을 . 기준으로 나눠 리스트로 변환 후 

5. 리스트의 i번째 값 가져오기 x.split('.')[i]

6. len() 의 길이<i 면 해당 인덱스가 존재하지 않음 : 나눈 문자열의 길이가 원래 문자열보다 작아야함.

    -> 조건문 inline if 

 .format() 
{순서1}{순서2}문자열.format(출력값1, 출력값2)

✅ df특정컬럼.apply() : 데이터프레임의 특정 컬럼에 대해 각 행(row) 별 함수 적용
     lamba x: ~ 일회용 함수를 정의하여 apply()에 적용

📌 inline if
     결과값(조건만족할때) if 조건 조건안만족할때 

 

 

rrule

날짜 데이터를 원하는 형태로 나타낼 수 있음.

라이브러리 불러오기

from datetime import datetime
from dateutil.rrule import rrule, DAILY, TU

# 빈 리스트 생성 후 날짜를 담아주기
a=[ ]

for date in weekly_rule:
    a.append(date.strftime('%Y-%m-%d'))

# 원하는 날짜형식 datetime(시간, 월, 일)

  • 주요 옵션
    • freq : 반복 주기를 나타내는 파라미터
              SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY 
    • dtstart: 반복이 시작하는 날짜와 시간
    • interval: 주기적으로 반복되는 간격
    • count: 생성할 날짜의 최대 수
    • until: 반복이 끝나는 날짜와 시간
  •  
from dateutil.rrule import rrule, DAILY
# 2023-02-01 부터 2023-03-01 까지 strf 사용하여 원하는 데이터 형식으로 출력.
weekly_rule = rrule(DAILY, dtstart=start_date, until=end_date)
# 빈 리스트 생성 후 날짜를 담아주기
a=[]
for date in weekly_rule:
    a.append(date.strftime('%Y-%m-%d'))

 

# Time_stamp의 날짜데이터를 원하는 방식으로 바꾸기

# df3 에 있는 날짜 데이터는 string
# string -> datetime -> string 의 형태로 변환
# 위에서 받은 리스트에 해당하는 데이터만 필터링하기 위함
# 날짜가 "일/월/연도" 순서라면 dayfirst=True 사용. (자동으로 변환)
df3['Time stamp2'] = pd.to_datetime(df3['Time stamp'], dayfirst=True).dt.strftime('%Y-%m-%d')
📌 날짜데이터의 변환
df3['Time stamp']
 
-- 날짜데이터 -> string 형태로 저장
pd.to_datetime() -- string ->날짜데이터 타입으로 변환 + 옵션 datyfirst=True : 날짜가 앞으로
 .dt.strftime('%Y-%m-%d') -- datetime -> string "YYYY-MM-DD"로 변환

 

# 라이브러리 불러오기
from datetime import datetime
from dateutil.rrule import rrule, DAILY, TU

# 시작 날짜, 종료날짜
start_date = datetime(2024, 2, 1)
end_date = datetime(2024, 3, 1)

# 2024-02-01 부터 2024-03-01 까지 strf 사용하여 원하는 데이터 형식으로 출력.
weekly_rule = rrule(DAILY, dtstart=start_date, until=end_date)

for date in weekly_rule:
    print(date.strftime('%Y-%m-%d'))

# 빈 리스트 생성 후 날짜를 담아주기
a=[]
for date in weekly_rule:
    a.append(date.strftime('%Y-%m-%d'))
    
# 2023-02-01 부터 2023-03-01 까지 strf 사용하여 원하는 데이터 형식으로 출력
weekly_rule = rrule(DAILY, dtstart=start_date, until=end_date)

# 데이터프레임에서 특정 날짜기간에 해당하는 데이터만 슬라이싱 하기 
# 빈 리스트 생성 후 날짜를 담아주기
a=[]
for date in weekly_rule:
    a.append(date.strftime('%Y-%m-%d'))
    
# df3 에 있는 날짜 데이터는 string 
# string -> datetimd -> string 의 형태로 변환
# 위에서 받은 리스트에 해당하는 데이터만 필터링하기 위함 
df3['Time stamp2'] = pd.to_datetime(df3['Time stamp']).dt.strftime('%Y-%m-%d')

mask =(df3['Time stamp2'].isin(a))
df3[mask]