[내배캠] 데이터분석 6기/본캠프 기록

[본캠프 11일차] ADsP 공부, SQL 공부, SQL 코드카타, 파이썬 코드카타, 아티클 스터디 ①

물맨두 2025. 3. 4. 23:01
chapter 2. 프로그래밍 기초 시작!

새로운 달, 새로운 조, 새로운 챕터로 새롭게 시작하는 날이었다.

이번 조원들과 한 달 간 잘 지낼 수 있었으면 좋겠다.

 

25034 일간 목표 및 주간 목표 설정을 위해 포스트잇에 끼적여봤다

오늘 한 일은,

  • [ADsP 자격증 챌린지] 5주차 수강하기
  • 파이썬 공부
    • [코드카타] 파이썬 3문제 풀기
  • SQL 공부
    • [라이브 세션] 6회차 수강하기
    • [라이브 세션] 3회차, 5회차 과제로 작성한 쿼리 혼자 리뷰하기
    • [코드카타] SQL 5문제 풀기
  •  첫 번째 아티클 스터디 진행하기 (누적은 16번(11+4+1))

 


 

ADsP 공부: [ADsP 자격증 챌린지] 5주차 수강하기


( 👇 [ADsP 자격증 챌린지] 5주차 강의와 이어지는 R에 대한 기본적인 설명을 공부한 글 👇 )

 

[본캠프 10일차] ADsP 공부, SQL 공부, 코드카타 복습(SQL만)

마참내 금요일3일 쉰다사실 금요일이라고 집중력은 그렇게 좋아지지 않았지만(진짜 왜지) 그래도 기분은 좋았으니까 오케이.오늘은 2주차 팀 과제 발표회도 있고, 2월의 마지막 날이기도 하고,

maandoo.tistory.com


R 데이터의 구조

  • 벡터
    • 위에 남겨놓은 지난 TIL 강의 정리 참고
  • 행렬
    • 2차원 구조를 가진 벡터, 행렬에 저장된 모든 데이터는 같은 타입
  • 배열
    • 3차원 이상의 구조를 갖는 벡터, 하나의 배열에 포함된 데이터는 모두 같은 타입
  • 리스트
    • 데이터 타입, 데이터 구조에 상관없이 사용자가 원하는 모든 것을 저장할 수 있는 자료구조
  • 데이터 프레임 R에서 가장 많이 활용하는 데이터 구조
    • 행렬과 유사한 2차원 목록 데이터 구조
    • 행렬과는 다르게 각 열이 서로 다른 데이터 타입을 가질 수 있음

R 기본 문법

연산자

  • 대입 연산자
    • < - , << - , = : 우항을 좌항에 대입
    • - > , - > > : 좌항을 우항에 대입
  • 비교 연산자
    • ==, !=, <, >, <=, >= 등
    • is.character(), is.numeric(), is.logical(), is.na(), is.null() : 괄호 안의 값이 해당 데이터 타입/해당 값인지 아닌지
  • 산술 연산자
    • +, -, *, /, ** 등
    • 주의
      • a%/%b : a를 b로 나눈 계산의
      • a%%b : a를 b로 나눈 계산의 나머지
  • 기타 연산자
    • ! : 부정 연산자 ( !TRUE ∴FALSE )
    • & : AND 연산자
    • | : OR 연산자

R 내장 함수

  • (~그때그때 찾아보아요~)

제어문

  • 반복문
    • for 반복문
    • while 반복문
  • 조건문
    • if ~ else 구문

사실 오늘 배운 내용은 시험에 나오기에 달달 외워하는 부분이 아니라 R을 다루기 위해 기본적으로 알아둬야 하는 기본 개념들을 배우는 파트여서 특별히 외우기 위해 기록할 내용은 없다.

앞으로 R을 다루면서 오늘 배운 내용들에 익숙해져야겠다.

 


 

SQL 공부①: [예제로 익히는 SQL] 6회차 수강하기

오늘 SQL 라이브 세션에선 주로 지난 3회차 과제와 4·5회차 과제로 나간 문제들에 대해 문제의 의도가 무엇이고 해당 문제를 풀기 위해선 핵심적으로 사용했어야 하는 부분은 무엇인지를 튜터님과 함께 되짚어 보는 시간이었다.

그래서 강의가 끝나고 나도 개인 공부 시간에 TIL로 기록해놓은 나의 쿼리들과 강사님이 이번 강의자료로 제공하신 쿼리를 비교해보면서 회고의 시간을 가졌다.

(아 그런데 사실 질문을 어떤 문제에서 했는지 기억이 안 난다, 어떡하지?)

 


3회차 과제 쿼리 리뷰

( 👇 작성했던 3회차 과제 쿼리 보러가기 👇 )

 

[본캠프 6일차] 팀플 주제 선정, 파이썬 코드카타, SQL 코드카타, SQL 공부, ADsP 공부

다시 찾아온 월요일.주말이 벌써 지나가버렸다는 소식이 믿기지 않지만 오늘도 오늘의 할 일을 성실히 하며 보내야 또 내일을 잘 보낼 수 있으니까 뭐라도 해봐야지! 주말이 벌써 지나가버렸다

maandoo.tistory.com

 

1. 집계함수의 활용

#1번 정답쿼리
#substr 대신 date_format(first_login_date,"%Y-%m") 도 정답입니다.
select serverno, 
       substr(first_login_date,1,7)as m, 
       count(distinct game_account_id) as usercnt 
from basic.users 
group by serverno, substr(first_login_date,1,7)
#내가 작성한 3회차-문제1의 쿼리
SELECT DISTINCT serverno,
       SUBSTR(first_login_date, 1, 7) month,
       count(game_account_id) game_account_id
FROM users
GROUP BY 1, 2
ORDER BY 1
  • DISTINCT의 사용
    • 정답: SELECT serverno, (…) COUNT(DISTINCT game_account_id) AS usercnt
    • 내거: SELECT DISTINCT serverno, (…) COUNT(game_account_id) game_account_id
    • 결과 테이블에서의 차이는 없지만 이는 우연의 일치일 뿐이고 조건1에서 요구한 내용이 "게임계정id 수를 중복값 없이 추출"하라는 것이었으니 DISTINCT의 위치는 game_account_id 컬럼 앞에 붙이는 것이 맞음
      (밑에서도 DISTINCT를 맘대로 적어대는 일이 많음.. 반성 또 반성)
  • GROUP BY절 작성 시 숫자(1, 2)보다 정확히 해당 컬럼의 이름(serverno 등)을 밝혀서 적는 편이 다른 사람이 쿼리를 볼 때 더 이해하기 좋기 때문에 이름으로 되도록 이름으로 적어주는 편이 좋다.

 

2. 집계함수와 조건절의 활용

#2번 정답쿼리 
select first_login_date, 
       count(distinct game_actor_id)as actor_cnt
from basic.users 
group by first_login_date
having count(distinct game_actor_id)>10;
#내가 작성한 3회차-문제2의 쿼리
SELECT DISTINCT first_login_date,
       count(game_actor_id) game_actor_cnt
FROM users
GROUP BY 1
HAVING count(game_actor_id) > 10
ORDER BY 1

 

  • DISTINCT의 위치 (정확히 써라) (그냥 우연히 일치했을 뿐)
  • GROUP BY절에 컬럼명 밝혀서 쓰도록 하자

 

3. 집계함수와 조건절의 활용

#3번 정답쿼리 
select serverno, 
       case when first_login_date <'2024-01-01' then '기존유저'
       else '신규유저' end as gb,
       count(distinct game_actor_id)as actor_cnt,
       avg(level)as avg_level
from basic.users 
group by serverno,
     case when first_login_date <'2024-01-01' then '기존유저' else '신규유저' end
;
#내가 작성한 3회차-문제3의 쿼리
SELECT DISTINCT serverno,
       IF(first_login_date<'2024-01-01', '기존', '신규') '유저 구분',
       COUNT(game_actor_id) game_actor_cnt,
       AVG(level) avg_level
FROM users
GROUP BY 1, 2
ORDER BY 1
  • IF문 사용하지 말고 CASE WHEN 구문을 사용하길 권장함.
  • DISTINCT의 위치 제대로 쓰기
  • GROUP BY절에 컬럼명 밝혀서 쓰도록 하자

4. 서브쿼리의 활용

#4번 정답쿼리
select *
from(	select first_login_date, count(distinct game_actor_id)as actor_cnt
		from basic.users  
		group by first_login_date
	)as a 
where actor_cnt>10
#내가 작성한 3회차-문제4의 쿼리
SELECT a.first_login_date,
       a.game_actor_cnt
FROM 
    (SELECT DISTINCT first_login_date,
           count(game_actor_id) game_actor_cnt
    FROM users
    GROUP BY 1
    ORDER BY 1) a
WHERE a.game_actor_cnt > 10
  • DISTINCT의 위치 제대로 쓰기
  • GROUP BY절에 컬럼명 밝혀서 쓰도록 하자

5. 서브쿼리의 응용 - 해당 문제는 튜터님이 현업에서 자주 사용했던 쿼리라고

#5번 정답쿼리 
select actor_cnt, 
       count(distinct game_account_id)as accnt # 서브쿼리에서 group by 를 사용해 주었으므로 해당 구문의 distinct 는 필수가아닙니다. 
from(	select game_account_id , 
               count(distinct game_actor_id) as actor_cnt 
        from basic.users 
        where level>=30 
        group by game_account_id 
        having actor_cnt>=2
	)as a 
group by actor_cnt
#내가 작성한 3회차-문제5의 쿼리
SELECT b.game_actor_cnt,
       COUNT(b.game_account_id) game_account_cnt
FROM 
	(SELECT DISTINCT a.game_account_id,
	       COUNT(a.game_actor_id) game_actor_cnt
	FROM 
		(SELECT *
		FROM users
		WHERE level >= 30
		ORDER BY level) a
	GROUP BY 1
	HAVING COUNT(a.game_actor_id)>=2) b
GROUP BY 1
ORDER BY 1

 

  • 조건1의 "레벨 30 이상"이라는 조건 하나 때문에 서브쿼리를 사용할 필요 없음. 
  • GROUP BY절에 컬럼명 밝혀서 쓰도록 하자

 

(근데 신기하게도 정답 쿼리와 내가 작성한 쿼리를 비교했을 때에 결과 테이블은 모두 동일했다.. 신기하네)


4·5회차 과제 쿼리 리뷰

( 👇 작성했던 4·5회차 과제 쿼리 보러가기 👇 )

 

[본캠프 10일차] ADsP 공부, SQL 공부, 코드카타 복습(SQL만)

마참내 금요일3일 쉰다사실 금요일이라고 집중력은 그렇게 좋아지지 않았지만(진짜 왜지) 그래도 기분은 좋았으니까 오케이.오늘은 2주차 팀 과제 발표회도 있고, 2월의 마지막 날이기도 하고,

maandoo.tistory.com

 

1. 오랜 기간 보호한 동물(1)

#https://school.programmers.co.kr/learn/courses/30/lessons/59044

select name,
      datetime 
from(   select animal_id, datetime, name 
        from animal_ins
    )as a 
left outer join # inner join 을 쓰게되면, 들어오고 and 입양된 동물이 출력되므로 사용할 수 없음 
    (   select animal_id 
        from animal_outs 
    )as b 
on a.animal_id=b.animal_id 
where b.animal_id is null #out 에 animal_id 가 있지 않은 경우. 즉, 입양을 가지 못한 동물 필터링 
order by datetime #datetime 이 작은 것부터 
limit 3 # 최대 3개까지 출력
#내가 작성한 4·5회차-문제1의 쿼리
SELECT ai.name,
       ai.datetime
FROM animal_ins ai LEFT JOIN animal_outs ao ON ai.animal_id = ao.animal_id
WHERE ao.animal_type IS NULL
ORDER BY ai.datetime LIMIT 3
  • WHERE절에 animal_outs 테이블의 animal_id 컬럼으로 IS NULL 조건을 걸어주는 것이 정석.

2. 조건에 맞는 사용자와 총 거래금액 조회하기

#https://school.programmers.co.kr/learn/courses/30/lessons/164668 

select b.user_id, nickname as NICKNAME, sum(price)as TOTAL_SALES
from(   select WRITER_ID, price 
        from used_goods_board
        where STATUS='DONE'#반드시 대소문자 구분해서 사용. 반드시 입력된 컬럼값 그대로 호출해야함 
    )as a
inner join # 중고거래 게시판에 있고 거래상태가 완료된 건. 두 테이블을 교집합
    (   select user_id, nickname
        from used_goods_user
    )as b 
on a.WRITER_ID=b.user_id 
group by b.user_id, nickname
having TOTAL_SALES>=700000
order by TOTAL_SALES asc
#내가 작성한 4·5회차-문제2의 쿼리
SELECT ugu.user_id,
       ugu.nickname,
       sum(ugb.price) total_sales
FROM used_goods_board ugb LEFT JOIN used_goods_user ugu ON ugb.writer_id = ugu.user_id
WHERE ugb.status = 'DONE'
GROUP BY 1
HAVING sum(ugb.price) >= 700000
ORDER BY 3
  • INNER JOIN으로 묶어주는 것이 더 효율적인 쿼리
    (∵전체 데이터가 굳이 필요 없는데 데이터 전체를 보려면 데이터가 클수록 시간이 많이 걸리니까)
  • GROUP BY절에 컬럼명 밝혀서 쓰도록 하자

3. 보호소에서 중성화한 동물

#https://school.programmers.co.kr/learn/courses/30/lessons/59045

select a.animal_id, animal_type, name
from(   select animal_id , animal_type, name
        from animal_ins 
        where SEX_UPON_INTAKE like('%Intact%')
    )as a
inner join 
    (   select animal_id 
        from animal_outs 
        where (SEX_UPON_OUTCOME like ('%Spayed%')) or (SEX_UPON_OUTCOME like ('%Neutered%'))
    )as b
on a.animal_id =b.animal_id
#내가 작성한 4·5회차-문제3 쿼리
SELECT ao.animal_id,
       ao.animal_type,
       ao.name
FROM animal_outs ao LEFT JOIN animal_ins ai ON ao.animal_id=ai.animal_id
WHERE (ai.sex_upon_intake LIKE 'Intact%')
      AND (ao.sex_upon_outcome NOT LIKE 'Intact%')

 

4. JOIN 활용

# 정답 쿼리
select case when b.game_account_id is null then '결제안함' else '결제함' end as gb
, count(distinct a.game_account_id)as usercnt 
from(	select game_account_id
		from basic.users 
	)as a 
left outer join 
	(	select game_account_id 
		from basic.payment
	)as b
on a.game_account_id=b.game_account_id
group by case when b.game_account_id is null then '결제안함' else '결제함' end
;
#내가 작성한 4·5회차-문제4 쿼리
SELECT CASE WHEN p.pay_amount IS NOT NULL THEN '결제를 한 유저'
       ELSE '결제하지 않은 유저' END gb,
       count(*) usercnt
FROM basic.users u LEFT JOIN basic.payment p ON u.game_account_id = p.game_account_id
GROUP BY 1

(좌) 정답 쿼리의 결과 테이블 / (우) 나의 쿼리의 결과 테이블

  • 결과 테이블이 서로 다른 이유
    • 조건2 충족을 위해 CASE WHEN 구문에 조건을 적을 때에 payment 테이블의 pay_amount 컬럼으로 조건을 줄 것이 아니라 조인할 때 사용한 두 테이블의 공통 컬럼인 game_account_id 컬럼을 사용해 조건을 주는 것이 적절
    • [참고] 조건2 'CASE WHEN 구문을 사용하여 결제를 한 유저와 결제를 하지 않은 게임계정을 구분하기'

5. JOIN 응용 1

# 정답 쿼리
select *
from(	select a.game_account_id, count(distinct game_actor_id) as actor_cnt, sum(pay_amount)as sumamount 
		from(	select game_account_id, game_actor_id 
				from basic.users 
				where serverno>=2
			)as a 
		inner join 
			(	select distinct game_account_id, pay_amount, approved_at
				from basic.payment
				where pay_type='CARD'
			)as b 
		on a.game_account_id=b.game_account_id 
		group by a.game_account_id
	)as a 
where actor_cnt>=2
order by sumamount desc
#내가 작성한 4·5회차-문제5 쿼리
SELECT *
FROM(
	SELECT u.game_account_id,
	       COUNT(u.game_actor_id) actor_cnt,
	       SUM(p.pay_amount) sumamount
	FROM(
		SELECT *
		FROM basic.users 
		WHERE serverno >= 2
		) u
	INNER JOIN 
		(
		SELECT *
		FROM basic.payment
		WHERE pay_type = 'CARD'
		) p
	ON u.game_account_id = p.game_account_id
	GROUP BY 1
	) gai
WHERE gai.actor_cnt >= 2
ORDER BY gai.sumamount DESC

(좌) 정답 쿼리의 결과 테이블 / (우) 나의 쿼리의 결과 테이블

  • 결과 테이블이 서로 다른 이유
    • 조건2 충족을 위해 컬럼 actor_cnt를 지정할 때에 COUNT(game_actor_id)가 아니라 중복값 없이 세도록 COUNT(DISTINCT game_actor_id)라고 작성했어야
    • [참고] 조건2 '조인한 결과를 바탕으로 users 테이블의 game_account_id를 기준으로 game_actor_id수를 중복값없이 세고 컬럼 이름을 actor_cnt로 지정해주세요'

6. JOIN 응용 2

# 정답 쿼리 
select serverno, round(avg(diffdate),0)as avgdiffdate
from(	select a.game_account_id, datediff(date_format(date2,('%Y-%m-%d')) ,first_login_date) as diffdate,serverno
			from(	  select game_account_id, first_login_date, serverno
					    from basic.users 
				   )as a
			inner join 
				   (	select game_account_id, max(approved_at)as date2 
					    from basic.payment
					    group by game_account_id
				    )as c 
			on a.game_account_id=c.game_account_id 
			where date2>first_login_date
		)as d 
where diffdate>=10
group by serverno
order by serverno desc
#내가 작성한 4·5회차-문제6의 쿼리
SELECT sdd.serverno,
       ROUND(AVG(sdd.diffdate)) avgdiffdate
FROM(
	SELECT u.serverno,
	       DATEDIFF(p.date2, u.first_login_date) diffdate
	FROM(
		SELECT game_account_id,
		       DATE_FORMAT(first_login_date, '%Y-%m-%d') first_login_date,
		       serverno
		FROM basic.users
		) u
	INNER JOIN
		(
		SELECT game_account_id,
		       DATE_FORMAT(MAX(approved_at), '%Y-%m-%d') date2
		FROM basic.payment
		GROUP BY 1
		) p
	ON u.game_account_id = p.game_account_id
	WHERE p.date2 > u.first_login_date
	) sdd
WHERE sdd.diffdate >= 10
GROUP BY 1
ORDER BY 1 DESC

 


📌SQL 작성 시 유의할 점📌

✔ GROUP BY절 작성 시, 되도록이면 숫자보다 컬럼명 밝혀서 쓰기
✔ DISTINCT 작성 시, 위치 혹은 누락되진 않았는지 주의하기
✔ JOIN 사용 시, 전체 테이블을 결합할 필요가 없다면 필요한 컬럼들만 조회하여 결합하는 습관 들이기

오늘 내가 제출했던 쿼리들을 리뷰하면서 공통적으로 반복된 사항들을 유념하기 위해 다시 정리해봤다.

생각보다 DISTINCT를 내가 생각 없이 쓰고 있음을(…) 깨닫고 많이 반성했다. 앞으로는 그러지 말아야겠다.

 


 

SQL 공부②: 코드카타 풀기(52~56번)

52. 과일로 만든 아이스크림 고르기

상반기 아이스크림 총주문량이 3,000보다 높으면서 아이스크림의 주 성분이 과일인 아이스크림의 맛을 총주문량이 큰 순서대로 조회하는 SQL 문을 작성해주세요.

SELECT fh.flavor
FROM (
     SELECT flavor,
            total_order
     FROM first_half
     WHERE total_order > 3000
     ) fh
     LEFT JOIN
     (
     SELECT flavor,
            ingredient_type
     FROM icecream_info
     WHERE ingredient_type = 'fruit_based'
     ) ii
     ON fh.flavor = ii.flavor
ORDER BY fh.total_order DESC

처음에는 위와 같이 쿼리를 작성했다.

그런데 제출하니 틀렸다고 하여 무엇이 문제인지 확인하기 위해 SELECT절에 first_half 테이블의 total_order 컬럼과 icecream_info 테이블의 ingredient_type 컬럼을 추가해봤다.

확인해보니 ingredient_type의 값이 fruit_based가 아니라서 NULL값이 뜨는 것까지 조회된 것을 보니 LEFT JOIN이 아닌 INNER JOIN을 사용했어야 함을 알았다.

그래서 다음과 같이 수정했다.

SELECT fh.flavor
FROM (
     SELECT flavor,
            total_order
     FROM first_half
     WHERE total_order > 3000
     ) fh
     INNER JOIN
     (
     SELECT flavor,
            ingredient_type
     FROM icecream_info
     WHERE ingredient_type = 'fruit_based'
     ) ii
     ON fh.flavor = ii.flavor
ORDER BY fh.total_order DESC

 

53. 재구매가 일어난 상품과 회원 리스트

ONLINE_SALE 테이블에서 동일한 회원이 동일한 상품을 재구매한 데이터를 구하여, 재구매한 회원 ID와 재구매한 상품 ID를 출력하는 SQL문을 작성해주세요. 결과는 회원 ID를 기준으로 오름차순 정렬해주시고 회원 ID가 같다면 상품 ID를 기준으로 내림차순 정렬해주세요.

SELECT user_id,
       product_id
FROM online_sale
WHERE COUNT(*) >= 2
GROUP BY user_id, product_id
ORDER BY user_id, product_id DESC

처음엔 이렇게 쿼리를 작성하고 코드 실행을 하려고 했는데 유효하지 않은 그룹 기능이라는 에러 메시지가 떴다.

그래서 WHERE절 조건이 잘못됐다는 것을 알아채고 다음과 같이 쿼리를 수정했다.

 

SELECT user_id,
       product_id
FROM online_sale
GROUP BY user_id, product_id
HAVING COUNT(*) >= 2
ORDER BY user_id, product_id DESC

WHERE절이 아니라 HAVING절로 조건을 주니 원하는 결과 테이블을 조회할 수 있었다.

 


 

파이썬 공부: 코드카타 풀기(42~44번)

43. 크기가 작은 부분문자열

숫자로 이루어진 문자열 t와 p가 주어질 때, t에서 p와 길이가 같은 부분문자열 중에서, 이 부분문자열이 나타내는 수가 p가 나타내는 수보다 작거나 같은 것이 나오는 횟수를 return하는 함수 solution을 완성하세요.

def solution(t, p):
    answer = 0
    for i in range(len(t)):
        t2 = t[i:i+len(p)]
        if int(p) <= int(t2):
            answer += 1
    return answer

첫 번째로 작성한 코드를 실행하니 테스트 케이스들을 전부 틀렸다.

그래서 print(t2), print(t2, answer)를 추가해서 연산한 내용을 확인해봤다.

...?

왜 이렇게 숫자를 세고 있는 거지..?

t2가 p보다 같거나 작을 때마다 answer에 카운팅이 되도록 했는데 크거나 같을 때 카운팅되고 있었다.

 

...

그렇다. 이제야 if문 조건이 잘못 주어졌음을 알아차렸다.. 하하.....하

그런데 그뿐만 아니라 t2로 p와 문자열 길이가 같은 것만을 비교하도록 하는 내용도 추가해야 함을 확인했다.

그래서 다음과 같이 코드를 수정했다.

def solution(t, p):
    answer = 0
    for i in range(len(t)):
        t2 = t[i:i+len(p)]
        if int(p) >= int(t2):
            if len(p) == len(t2):
                answer += 1
    return answer

 


 

아티클 스터디 ①: 사용자 데이터를 효과적으로 분석하는 법

오늘 읽은 아티클:

 

사용자 데이터를 효과적으로 분석하는 법 | 요즘IT

사용성 평가나 설문 조사 그리고 인터뷰와 같은 사용자 조사는 고객 관점에서의 사업 기회 발굴과 디자인 개선에 대한 인사이트를 제공해 줍니다. 그렇지만 단순히 사용자 조사로 수집된 데이

yozm.wishket.com

 

250304 오늘 진행한 아티클 스터디 중 개인 요약 한 일부

오늘 읽은 아티클을 통계 분석에 대해서 기본적인 틀을 잡을 수 있었다.

그래서 다시 아티클의 내용을 정리해보는 것도 기초 통계적인 지식이 없는 내게 많은 도움이 될 것 같아서 다시 한 번 정리해보았다.

 

  • 1️⃣정량적 데이터(Quantitative Data)를 분석할 땐 통계 분석(Statistical analysis)을 사용한다
    • 정량적 데이터
      • 만족도 점수, 과제 수행 시간, 에러 수 등
      • 얼마나 많은 행동이 일어나고 있는지를 알려준다
  • 2️⃣통계 분석은 기술 통계(Descriptive statistics)와 추론 통계(Inferential statistics)로 구분한다
    • 기술 통계는 수집한 데이터의 특성을 파악하기 위해 활용한다
    • 추론 통계는 샘플을 통해 모집단을 추론하거나 가설 검정을 하기 위해 활용한다
    • 기본적으로 데이터 특성을 파악하기 위해 기술 통계를 진행한 후, 더 고도화된 분석이 필요할 때 추가적으로 추론 통계까지 진행한다.
  • 3️⃣기술 통계의 경우,
    • 데이터 유형에 따라 다른 통계값을 구한다.
      • 범주형 데이터(선호하는 디자인 타입, 과제 성공 여부 등) → 빈도, 백분율 등
      • 수치형 데이터(만족도, 수행 시간 등) → 평균, 표준 편차 등
    • 대표적인 통계값 : 중심 경향(Central tendency) 지표 (평균, 중앙값, 최빈값 등)
      • 평균이 가장 널리 활용되나, 활용 시 극단값이 포함되는 경우 평균에 영향을 크게 주므로 해석에 주의해야 함
      • 극단값을 많이 포함할 경우 중앙값을 활용하길 고려해 볼 수 있음
      • 최빈값은 주관적인 척도처럼 데이터가 제한된 값을 가지고 있을 때 활용하길 고려해 볼 수 있음
      • 분석 시에 참가자의 실수로 수집된 이상값을 제거하고서 분석하는 방법 역시 고려해봐야 함
    • 기술 통계 분석의 시각화
      • 범주형 데이터 → 파이 차트(원 그래프), 누적 막대그래프
      • 수치형 데이터 → 막대 그래프, 꺾은선 그래프
      • 이 외에도 방사형 그래프, 산점도  등
  • 4️⃣추론 통계의 경우,
    • 추론 통계에 들어가기 전 알아둬야 하는 기본 개념
      • 모집단은 전체 사용자 집단을 의미하고, 표본은 사용자 집단 중 참가한 일부 사용자들을 의미한다.
        (∵전체 사용자를 대상으로 조사하는 것은 시간과 비용 측면에서 불가능하기에 표본 조사를 진행함)
      • 이때 모집한 표본으로부터 수집된 데이터가 과연 전체 사용자를 대표할 수 있을까?
        • ①데이터의 정규성이 확보되는가?
        • ②데이터의 정규성이 확보되었다면, 추론 통계의 분석 결과가 통계적으로 유의미한가?
    • 대표적인 추론 통계 방법
      • t 검정, 분산 분석(ANOVA) : 단순 변수들 간 통계적 차이가 있는가를 살펴봄
        • 비교하는 대상이 2개 이하 → t 검정
        • 비교하는 대상이 2개 초과 → 분산 분석
      • 상관 분석(Correlation analysis), 회귀 분석(Regresion analysis) : 변수들 간의 관계를 파악하는 데 활용
        • 2개 이상의 변수들의 선형적 관계를 살펴보자 → 상관 분석
        • 하나의 종속 변수에 대해 다수의 독립변수들이 어떻게 영향을 비치는지 인과 관계를 알아보자 → 회귀 분석
  • 5️⃣현업에서 통계 분석 사용 시 주의사항
    • 기술 통계의 경우 Excel에서 간단한 함수를 통해 쉽게 활용할 수 있는 반면에, 추론 통계의 경우 심리학적 실험 설계 방법 및 통계 분석 같은 전문 지식과 통계 전용 분석 툴(SPSS, SAS 등)을 활용할 줄 알아야 함
    • 그래프를 그릴 때 왜곡이 발생하지 않도록 주의하여 중요한 차이나 변화의 흐름을 정확히 보여주는 것이 필요함
    • 통계적 유의차가 나타나지 않는 경우
      ⇒ 사용자 유형에 따른 데이터를 분석해 서비스 타깃으로 하는 유형이 더 선호하는 컨셉은 무엇인지를 파악하는 방향으로 접근 시도
    • 데이터만으로 의사결정이 쉽지 않은 경우
      ⇒ 결국은 해석하는 사람의 의사결정이 필요함. 데이터가 수집된 환경에서 포함되지 않았던 맥락적 배경을 검토해야 함

 


 

이번 주는 팀 과제 없으니까 이럴 때 온라인 강의들을 열심히 봐놓아야겠다.