OkBublewrap

2024-12-23 TIL (Retension, Python 기본) 본문

Today I Learning

2024-12-23 TIL (Retension, Python 기본)

옥뽁뽁 2024. 12. 23. 09:46

아티클 # 13

 

AB180 Blog | 리텐션에 영향을 미치는 요인을 찾는 7가지 데이터 분석 방법

이번 포스트에서는 각 코호트 및 페르소나에 대한 베이스라인 메트릭을 확인해보고, 리텐션에 영향을 미치는 요인을 확인할 수 있는 7가지 데이터 분석 방법들을 Amplitude의 고객 사례 및 대시보

blog.ab180.co

 

1. 아티클 주요 내용 요약

  • 핵심 주제: 리텐션에 영향을 미치는 요인을 확인할 수 있는 7가지 데이터 분석 방법
  • 주요 내용:
    • 어떤 페르소나가 다른 페르소나에 비해 리텐션이 높은가?
    • 더 높은 고객 생애 가치(LTV)를 가진 페르소나는 무엇인가?
    • 어떠한 액션이 이들 메트릭에 기여하는가?
    • 어떻게 더 많은 유저들이 가치가 높은 페르소나에 속하도록 만들 수 있는가?
    • 1. 베이스라인 리텐션 그리기(N-day, Unbounded, Bracket)
    • 2. 행동 페르소나의 리텐션 커브 비교
    • 3. 유저 속성을 분석하고 핵심 유저 속성 정의하기(국적, 나이, 사용언 언어, 플랫폼 등등)
    • 4. 행동 코호트(특정 행동 한 유저, 수행하지 않은 유저)
    • 5. 핵심 경로 퍼널을 통한 전환율 파악
    • 6. 활동 경로 탐색으로 유저 행동 파악
    • 7. 밀착도 측정으로 유저의 사용 빈도 확인(Stickiness)
    • 8.세션 메트릭으로 유저 인게이지먼트 확인하기

 

2. 인사이트 및 배운 점

  • 배운 점 :  리텐션을 영향을 미치는 요인을 알려면 세분화의 세분화를 진행하면서 비교를 해봐야한다. 왜 이 세그먼트는 잔존율이 다른 세그먼트보다 높은지, 저렇게 잔존율 만큼 올리려면 어떻게 해야하는지 방법을 찾아야 한다. 다른 아티클을 읽으면서 보니 결국 중요한 거는 고객을 이해한다는 것. 우리의 플랫폼을 고객에게 설득하는 과정이다.
  • 활용 방안 : 활동 경로 탐색을 한번 진행을 해보고 싶다.

 

3. 생각 및 의견

  • 나의 의견 : 행동 코호트, 지역별 세그먼트로 나눠서 진행을 했다. 지역별로 보니 문제점을 발견을 했다. 
  • 의문점 : 이 사람이 우리의 플랫폼의 핵심 고객인가를 추정을 어떻게 하는지 모르겠다. 

 

4. 추가 계획

플랫폼의 로그 데이터에 이해도가 생겼고, 또 리텐션을 어떻게 활용할 수 있는지를 배울 수 있는 기간이였다.

 

 


 

파이썬 

1. 클로저와 데코레이터

클로저(Closure)

  • 함수 안의 함수를 결과로 반환할 때, 그 내부 함수를 클로저라고 한다.
  • 사용처
    • 콜백(Callback) 함수에 사용
    • 함수의 순차적 실행
    • 데코레이터 함수
# 클래스 이용하기
class Mul:
    def __init__(self, m):
        self.m = m

    def mul(self, n):
        return self.m * n

if __name__ == "__main__":
    mul3 = Mul(3)
    mul5 = Mul(5)

    print(mul3.mul(10))  # 30 출력
    print(mul5.mul(10))  # 50 출력
# 2 클로저 사용하기

def mul(m):           # 외부 함수
    def wrapper(n):   # 내부 함수 (클로저)
        return m * n
    return wrapper
    
if __name__ == "__main__":
    mul3 = mul(3)    # m = 3 인 wrapper 함수가 mul3 에 저장 
    mul5 = mul(5)    # m = 5 인 wrapper 함수가 mul5 에 저장

    print(mul3(10))  # m = 3, n = 10 인 wrapper 함수가 실행
    print(mul5(10))  # m = 5, n = 10 인 wrapper 함수가 실행

데코레이터

  • @를 이용한 어노테이션으로 사용
  • 사용하는 곳
    • 반복되는 작업을 여러 함수에 적용할 경우
    • 기존 함수를 수정하지 않고 추가 기능을 구현하고 싶을 경우
# 데코레이터 사용
import time

def func1(a, b):
    val = a + b   
    return val

def func2(a, b):
    val = a * b   
    return val
    
def elapsed(func):                                     # 함수를 인풋으로 받는다.
    def wrapper(a, b):
        print('함수가 실행됩니다.')
        start = time.time()
        result = func(a, b)                            # 함수 실행
        end = time.time()
        print("함수 수행시간: %f 초" % (end - start))  # 함수 수행시간
        return result                                  # 함수 실행 결과 반환
    return wrapper
    
# 클로저 사용
if __name__ == "__main__":
    deco1 = elapsed(func1)
    result = deco1(1,2)
    print(result)
    
# 데코레이터 사용
@elapsed
def func1(a, b):
    val = a + b   
    return val

 

 

2. 이터레이터와 제너레이터

이터레이터

  • 집합에서 값을 차례대로 꺼낼 수 있는 객체(Objcet)
  • 반복 가능 객체에만 사용가능
    • iter()로 반복 가능 객체 변환
    • next()로 다음값 뽑기
  • 한번 반복하면 다시 사용될 수 없음
# 이터레이터 만들기
# iter()
# next()

a = [1,2,3]
iterator = iter(a)

type(iterator)
# list_iterator

next(iterator)
# 1
next(iterator)
# 2
next(iterator)
# 3

for a in iterator:
    print(a)
    
# 1
# 2
# 3

 

제너레이터

  • 이터레이터를 생성하는 함수
  • 함수가 하나의 고정된 값을 반환하는 것이 아닌 순차적으로 다른 값을 반환하기 원할 때
  • yield()
# 제너레이터
def generator():
    yield 'a'
    yield 'b'
    yield 'c'
    
g = generator()
type(g)
# generator

next(g)
# 'a'

next(g)
# 'b'

next(g)
# 'c'


# 예시
def clinet_count(total_client):
	n = 1
    for num in range(total_clinet):
    	print(f'{n} 번째 고객님 입장하십시오!')
        n += 1
        yield
 
mygen = client_count(100)
next(mygen)
# 1번째 고객님 입장하십시오!
next(mygen)
# 2번째 고객님 입장하십시오!
next(mygen)
# 3번째 고객님 입장하십시오!

 

3. 변수 타입 어노테이션

타입 어노테이션

  • 타입 어노테이션 : 변수나 상수를 선언할 때 그 타입을 명시적으로 선언해 줌으로써 어떤 타입의 값이 저장될 것인지를 직접 알려주는 방법
  • 프로그램은 수많은 함수, 클래스 등으로 복잡하게 얽혀있는 경우가 많은데, 변수 타입이 맞지 않응면 에러나 버그의 발생 가능성이 높아짐
  • 사용 시, 코드 가독성과 협업 효율성이 높아짐
  • 파이썬은 프로그램 실행 도중 변수 타입을 동적으로 바꿀 수 있는 동적 프로그래밍 언어

 

동적 프로그래밍 언어의 장단점

  • 장점 
    • 타입에 자유로워 유연한 코딩하므로 쉽고 빠르게 프로그램을 만들 수 있음
    • 타입 체크를 위한 코드가 없으므로 비교적 깔끔한 소스 코드
  • 단점
    • 프로젝트의 규모가 커질수록 잘못된 타입 사용으로 말미암은 버그가 생길 확률 높아짐
    • 타입 어노테이션이 없을 시, 정적 프로그래밍 언어와 타입 버그 발생 시 원인 찾기 어려움
    • 실행속도가 느림
def add(a : int, b : int) -> int:
	return a + b
    
add(1, 2)
# 3

add("1", "2") # 에러가 나지는 않음
# '12'

# 타입 어노테이션 확인
add.__annotations__
# {'a' : int, 'b' : int, 'return' : int}

 

 

4. 문자열 처리

str(), repr() 함수

  • str()과 repr()은 모두 객체를 문자열로 반환하는 함수
  • str()은 비공식적인 문자열을 출력
  • repr()은 공식적인 문자열을 출력 (시스템에서 인식가능)
구분 str() repr()
성격 비공식적인 문자열을 출력 공식적인 문자열을 출력
사용 목적 사용자가 보기 쉽도록 문자열로 객체를 다시 생성
누구를 위해 프로그램 사용자 프로그램 개발자

 

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"{self.name} ({self.age} years old)"

    def __repr__(self):
        return f"Person('{self.name}', {self.age})"

# 객체 생성
person = Person('Alice', 30)

# str()과 repr() 사용
print(str(person))   # 출력: Alice (30 years old)
print(repr(person))  # 출력: Person('Alice', 30)