안녕하세요. 다익스트라는 에지의 가중치가 양수일때 출발노드에서 전체 각 노드까지의 최단거리, 벨만-포드는 특정 출발노드에서 다른 노드까지의 최단 경로 탐색, 음수 가중치가 있어도 수행 가능 이렇게 되어있는데, 벨만-포드에서 에지 사용 횟수를 강조하는 이유가 다익스트라는 출발 노드가 정해져있고, 벨만-포드는주어진 출발노드가 달라질수 있어서라고 생각하면 될까요..? 처음엔 가중치 양수, 음수만의 차이만 인줄 알았는데, 뭔가 강조하시는걸 보니 저런 이유때문인가하고 질문해봅니다..! 다들 화이팅
n,m=map(int,input().split()) weight=list(map(int, input().split())) left=0 right=(n-1) cnt=0 weight.sort() while left<=right: weight_sum=weight[left]+weight[right] if weight_sum>m: cnt+=1 right-=1 else: cnt+=1 left+=1 right-=1 print(cnt) 안녕하세요 선생님, 이렇게 left, right 포인터를 이용해서 풀어도 예제 문제는 모두 정답이 나오는데 혹시 이렇게 푸는 풀이도 답으로 가능할까요?
package com.jinyoung.myapplication import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter class ListViewAdapter(var List : MutableList<String>) : BaseAdapter() { override fun getCount(): Int { return List.size } override fun getItem(p0: Int): Any { return List[p0] } override fun getItemId(p0: Int): Long { TODO("Not yet implemented") } override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View { TODO("Not yet implemented") } } 이 코드에서 3번째 함수 getItemId 함수의 return 값이 List[p0].toLong()이 되어야하는거 아닌가요????
안녕하세요. 좋은 강의 감사합니다! a와 b의 최대 공약수 시간 복잡도에 대해 질문이 있는데요. 약수를 구하는 시간 복잡도가 O(√n)이고, 최대 공약수를 구하기 위해서는 a, b 각각의 약수를 구하는 연산이 들어가기 때문에 최소 O(√a + √b)가 될 텐데 어떻게 O(√max(a, b))가 나오게 되는지 궁금합니다.
현재 섹션 5의 3번째 영상을 보고 있습니다. category = models.ForeignKey( Category, on_delete=models.CASCADE, db_constraint=False, ) 위 코드에서 카테고리에 왜 db_constraint=False, 를 설정하였는지 이해가 잘 되지 않아 설정 용도에 대해 알고 싶습니다. default=null을 한다면, 카테고리 외래키 없이 product 데이터를 생성할 목적인걸 알겠는데, 없는 상황에서 어떤 이유에 사용하신 것인지 알고 싶습니다.
SELECT [1, 2, 3, 4, 5] AS some_numbers ; SELECT ARRAY<INT64>[1, 2, 3, 4, 5] AS some_numbers ; SELECT GENERATE_ARRAY(1, 5, 1) AS some_numbers ; SELECT [SAFE_OFFSET()] ; SELECT (1, 2, 3) AS struct_test ; SELECT STRUCT<hi INT64, hello INT64>(1, 2) AS struct_test ; SELECT a.title, b AS genre FROM workspace.array_exercises AS a JOIN UNNEST(genres) AS b ; SELECT a.title, b.actor, b.character FROM workspace.array_exercises AS a JOIN UNNEST(actors) AS b ; SELECT a.title, b.actor, b.character, c AS genre FROM workspace.array_exercises AS a JOIN UNNEST(actors) AS b JOIN UNNEST(genres) AS c ; SELECT a.user_id, a.event_date, a.event_name, a.user_pseudo_id, b.key, b.value.string_value, b.value.int_value FROM workspace.app_logs AS a JOIN UNNEST(event_params) AS b ; SELECT key, string_value, count(distinct user_pseudo_id) FROM ( SELECT a.user_id, a.event_date, a.event_name, a.user_pseudo_id, b.key, b.value.string_value, b.value.int_value FROM workspace.app_logs AS a JOIN UNNEST(event_params) AS b ) WHERE event_name = 'screen_view' GROUP BY ALL ; SELECT order_date, sum(if(user_id = 1, amount, 0)) as user_1, sum(if(user_id = 2, amount, 0)) as user_2, sum(if(user_id = 3, amount, 0)) as user_3 FROM workspace.orders GROUP BY ALL ORDER BY order_date ; SELECT user_id, sum(if(order_date = '2023-05-01', amount, 0)) `2023-05-01`, sum(if(order_date = '2023-05-02', amount, 0)) `2023-05-02`, sum(if(order_date = '2023-05-03', amount, 0)) `2023-05-03`, sum(if(order_date = '2023-05-04', amount, 0)) `2023-05-04`, sum(if(order_date = '2023-05-05', amount, 0)) `2023-05-05` FROM workspace.orders GROUP BY ALL ORDER BY user_id ; SELECT user_id, if(sum(if(order_date = '2023-05-01', amount, 0)) > 0, 1, 0) `2023-05-01`, if(sum(if(order_date = '2023-05-02', amount, 0)) > 0, 1, 0) `2023-05-02`, if(sum(if(order_date = '2023-05-03', amount, 0)) > 0, 1, 0) `2023-05-03`, if(sum(if(order_date = '2023-05-04', amount, 0)) > 0, 1, 0) `2023-05-04`, if(sum(if(order_date = '2023-05-05', amount, 0)) > 0, 1, 0) `2023-05-05` FROM workspace.orders GROUP BY ALL ORDER BY user_id ; WITH events AS ( SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, platform, MAX(IF(b.key = "firebase_screen", b.value.string_value, NULL)) AS firebase_screen, MAX(IF(b.key = "session_id", b.value.string_value, NULL)) AS session_id FROM workspace.app_logs AS a JOIN UNNEST(event_params) AS b WHERE event_date >= '2022-08-01' AND event_date < '2022-08-19' GROUP BY ALL ), filter_event_and_concat_event_and_screen AS ( SELECT * EXCEPT(event_name, firebase_screen, event_timestamp), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM events WHERE event_name IN ('screen_view', 'click_payment') ) SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = 'screen_view-welcome' THEN 1 WHEN event_name_with_screen = 'screen_view-home' THEN 2 WHEN event_name_with_screen = 'screen_view-food_category' THEN 3 WHEN event_name_with_screen = 'screen_view-restaurant' THEN 4 WHEN event_name_with_screen = 'screen_view-cart' THEN 5 WHEN event_name_with_screen = 'click_payment-cart' THEN 6 END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM filter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL ;
1 from statsmodels.formula.api import ols from statsmodels.stats.anova import anova_lm model = ols('토마토수 ~ C(종자) * C(비료)', data=df).fit() anova_lm(model) 2 import statsmodels.api as sm from statsmodels.formula.api import ols model = ols('토마토수 ~C(종자)*C(비)', data=df).fit() anava_table=sm.stats.anova_lm(model) print(anava_table) 1 과 2를 보면 from statsmodels.formula.api import ols 는 같고 import statsmodels.api as sm과 from statsmodels.stats.anova import anova_lm이 다른데요.. 구글링해보고 고민해봐도 모르겠어요. 결과값은 같은데..무슨차이일까요?
SPP Layer의 경우 여러 Spatial Bins를 사용하여 이미지의 작은 부분부터 큰 부분까지의 정보를 취합하는 것으로 이해했습니다. 또한 ROI Pooling Layer의 경우 SPP Layer에서 Level이 1인 Bins만 적용하는 것으로 이해했습니다. 여기서 의문이 드는 것이 여러 정보를 종합적으로 취합한 SPP Layer가 ROI Pooling Layer보다 성능이 뛰어날 것으로 (직관적으로) 생각이 드는데, Fast RCNN에서 ROI Pooling을 선택한 이유가 궁금합니다. 실험적인 결과로 ROI Pooling을 선택했겠지만, ROI Pooling이 SPP Layer보다 Object Detection에서 우수한 성능을 보이는 이유가 궁금합니다!
ARRAY, STRUCT 연습문제 -- 1)영화별 장르를 unnest해서 보여줘라. SELECT title, genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) AS genre; --2) 영화별 배우와 배역을 보여줘라. 배우와 배역은 별도의 컬럼으로 나와야 한다. SELECT title, ac.actor, ac.character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS ac; --3. 영화별로 배우, 배역, 장르를 출력해라. SELECT title, actor.actor, actor.character, genre FROM `advanced.array_exercises` CROSS JOIN UNNEST(actors) as actor CROSS JOIN UNNEST(genres) as genre; --4. 앱 로그 데이터의 배열을 풀어라 SELECT user_id, event_date, event_name, user_pseudo_id, event_param.key, event_param.value.string_value, event_param.value.int_value FROM `advanced.app_logs` CROSS JOIN UNNEST(event_params) AS event_param PIVOT 연습문제 -- 1. 유저별 주문금액의 합계를 poviot해라. -- SELECT -- order_date, -- SUM(IF(user_id = 1, amount, 0)) AS user_1, -- SUM(IF(user_id = 2, amount, 0)) AS user_2, -- SUM(IF(user_id = 3, amount, 0)) AS user_3 -- FROM `advanced.orders` -- GROUP BY order_date -- ORDER BY order_date; -- 2. 날짜별 유저들의 주문금액의 합계를 pivot해라. -- SELECT -- user_id, -- SUM(IF(order_date = '2023-05-01', amount, 0)) AS `2023-05-01`, -- SUM(IF(order_date = '2023-05-02', amount, 0)) AS `2023-05-02`, -- SUM(IF(order_date = '2023-05-03', amount, 0)) AS `2023-05-03`, -- SUM(IF(order_date = '2023-05-04', amount, 0)) AS `2023-05-04`, -- SUM(IF(order_date = '2023-05-05', amount, 0)) AS `2023-05-05` -- FROM advanced.orders -- GROUP BY user_id -- ORDER BY user_id; -- 3. 사용자별, 날짜별 주문이 있다면 1, 없다면 0으로 pivot해라. -- SELECT -- user_id, -- MAX(IF(order_date = '2023-05-01', 1, 0)) AS `2023-05-01`, -- MAX(IF(order_date = '2023-05-02', 1, 0)) AS `2023-05-02`, -- MAX(IF(order_date = '2023-05-03', 1, 0)) AS `2023-05-03`, -- MAX(IF(order_date = '2023-05-04', 1, 0)) AS `2023-05-04`, -- MAX(IF(order_date = '2023-05-05', 1, 0)) AS `2023-05-05` -- FROM advanced.orders -- GROUP BY user_id -- ORDER BY user_id; --4. key값을 column으로 pivot해라 SELECT user_id, event_date, event_name, user_pseudo_id, IF(key = 'food_id', IF(string_value IS NOT NULL, string_value, CAST(int_value AS STRING)), NULL) AS food_id FROM advanced.app_logs_unnest # app_logs 테이블을 unnest한 결과는 자주 쓰일 듯 싶어 app_logs_unnest 테이블을 따로 생성했다. WHERE event_name = 'click_cart' AND event_date = '2022-08-01'; 기억할 것 IF 조건문을 사용할 때, TRUE일때의 값과 FALSE일때의 값의 데이터 타입이 같아야 한다. PIVOT 연습문제 4번을 풀 때 food_id를 PIVOT하는 과정에서 IF(key = 'food_id', IF(string_value IS NOT NULL, string_value, int_value AS STRING), NULL)와 같이 표현했었다. KEY값에 따라 string_value와 int_value중 타입에 맞는 하나의 컬럼에만 값이 있었고, 처음에는 이를 명시적으로 적기보다 범용적으로 사용될 수 있도록 하는게 더 좋지 않을까 싶었다. 값이 있는 컬럼의 값을 사용하자는 의도로 IF(string_value IS NOT NULL, string_value, int_value AS STRING)라고 표현했고 다음과 같은 에러를 만났다. No matching signature for function IF for argument types: BOOL, STRING, INT64. Supported signature: IF(BOOL, ANY, ANY) at [55:23] 에러를 피하고자 CAST를 이용했는데 데이터 타입을 억지로 바꾸기보다는(추후에 숫자형 데이터로 대소 비교를 한다던지 나열을 한나던지의 상황이 있을 수 있으니..) 명시적으로 표현하는 것을 마냥 피할것은 아니겠다는 생각을 했다. 특별한 문자(예약어, 숫자)를 ALIAS로 설정하려면 back tick(`) 으로 감싸줘야한다. 퍼널 쿼리 연습문제 -- 퍼널 별 유저 수 집계(2022-08-01 ~ 2022-08-18) -- welcome -> home -> good category -> restaurant -> cart -> 주문하기 클릭 /* event_data | event_name_with_screen | stemp_number | cnt 의 컬럼 형태로 만들것 */ -- 처음 작성했던 쿼리 -- SELECT -- event_date, -- CASE -- WHEN event_name = 'screen_view' AND string_value = 'welcome' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'home' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'food_category' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'restaurant' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'screen_view' AND string_value = 'cart' THEN CONCAT(event_name, '-', string_value) -- WHEN event_name = 'click_payment' AND string_value = 'cart' THEN CONCAT(event_name, '-', string_value) -- END AS event_name_with_screen, -- CASE -- WHEN event_name = 'screen_view' AND string_value = 'welcome' THEN 1 -- WHEN event_name = 'screen_view' AND string_value = 'home' THEN 2 -- WHEN event_name = 'screen_view' AND string_value = 'food_category' THEN 3 -- WHEN event_name = 'screen_view' AND string_value = 'restaurant' THEN 4 -- WHEN event_name = 'screen_view' AND string_value = 'cart' THEN 5 -- WHEN event_name = 'click_payment' AND string_value = 'cart' THEN 6 -- END AS step_number, -- COUNT(event_date) AS cnt -- FROM `advanced.app_logs_unnest` -- WHERE -- event_date BETWEEN '2022-08-01' AND '2022-08-18' -- GROUP BY ALL -- ORDER BY event_date, step_number -- ============================================= -- 정석 쿼리 WITH base AS( SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, platform, MAX(IF(event_param.key = "firebase_screen", event_param.value.string_value, NULL)) AS firebase_screen, MAX(IF(event_param.key = "food_id", event_param.value.int_value, NULL)) AS food_id, MAX(IF(event_param.key = "session_id", event_param.value.int_value, NULL)) AS session_id FROM `advanced.app_logs` CROSS JOIN UNNEST(event_params) AS event_param -- WHERE -- event_date = "2022-08-01" -- event_date BETWEEN "2022-08-01" AND "2022-08-18" -- AND -- event_param.key IN ("screen_view", "click_payment") -- AND -- event_param.value.string_value IN ("welcome", "home", "food_category", "restaurant", "cart") GROUP BY ALL ), filter_event_and_concat_event_and_screen AS( SELECT * EXCEPT(event_name, firebase_screen), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), "Asia/Seoul") AS event_datetime FROM base WHERE event_date BETWEEN "2022-08-01" AND "2022-08-18" AND event_name IN ("screen_view", "click_payment") AND firebase_screen IN ("welcome", "home", "food_category", "restaurant", "cart") ) SELECT event_date, event_name_with_screen, -- event_datetime, -- user_pseudo_id, CASE WHEN event_name_with_screen = 'screen_view-welcome' THEN 1 WHEN event_name_with_screen = 'screen_view-home' THEN 2 WHEN event_name_with_screen = 'screen_view-food_category' THEN 3 WHEN event_name_with_screen = 'screen_view-restaurant' THEN 4 WHEN event_name_with_screen = 'screen_view-cart' THEN 5 WHEN event_name_with_screen = 'click_payment-cart' THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM filter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL ORDER BY event_date, step_number 기억할 것 각 컬럼에 어떤 값이 있는지 잘! 확인하자. event_name_with_screen 부분을 CASE WHEN으로 처리하며 '이게 진정 맞을까......' 싶긴 했었었다. 왜인지 초반에 컬럼값 확인할 때 WHERE 절에 IN 구문으로 확인했을때 원하던 결과로 나오지 않아 CASE WHEN으로 직접 처리했었는데.. 실수였다. (아마 string_value만 IN연산으로 확인하고 섣부른 판단을 했던게 아닐지 싶다.) CASE WHEN 구문에서 전체를 포함하도록 조건을 구성하지 않으면 WHEN에 해당하지 않는 부분은 NULL값으로 생성된다. 처음 쿼리를 짜고 CNT 컬럼의 값을 확인했을 때 event_name_with_screen과 step_number에 왜 NULL값이 있는지 당황스러웠다. 이미 있는 데이터에 새 컬럼을 만든 것이니 조건에 해당되지 않는 부분은 값이 없어 NULL로 남아있다는 사실...! DATETIME 함수를 이용하여 "Asia/Seoul" 처리하기 새까맣게 잊고있었다. 까먹지 말자~! 항상 데이터를 뽑아 어떤 내용을 확인하고 싶은 건지 를 생각하자. 문제에 맞는 쿼리를 짜고 작성된 쿼리의 결과가 잘 나오는지에만 급급했던 거 같다. 이 강의를 듣는 목적은 데이터 분석에 대한 감 잡기!지 쿼리 잘 짜기!는 아니었으니까..!(물론 SQL 실력 향상은 필요한 부분..!!) 스스로 고민해보는 시간을 꼭! 갖도록 해보자.
1) ARRAY, STRUCT 연습문제 1-1) SELECT title, genre FROM advanced.array_exercises CROSS JOIN UNNEST (genres) as genre ORDER BY title; 1-2) SELECT title, actor.actor, actor.character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) as actor ORDER BY title; 1-3) SELECT title, actor.actor, actor.character, genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) as genre CROSS JOIN UNNEST(actors) as actor ORDER BY 1,2,3; 1-4) SELECT user_id, event_date, event_name, user_pseudo_id, event_param.key, event_param.value.string_value, event_param.value.int_value FROM advanced.app_logs CROSS JOIN UNNEST(event_params) as event_param WHERE event_date = '2022-08-01'; 2) PIVOT 연습문제 2-1) 1) SELECT order_date, SUM(IF(user_id = 1, amount, 0 )) AS user_1, SUM(IF(user_id = 2, amount, 0 )) AS user_2, SUM(IF(user_id = 3, amount, 0 )) AS user_3 FROM advanced.orders GROUP BY 1 ORDER BY 1; 2-2) SELECT user_id, SUM(IF(order_date = '2023-05-01', amount, 0)) AS `2023-05-01`, SUM(IF(order_date = '2023-05-02', amount, 0)) AS `2023-05-02`, SUM(IF(order_date = '2023-05-03', amount, 0)) AS `2023-05-03`, SUM(IF(order_date = '2023-05-04', amount, 0)) AS `2023-05-04`, SUM(IF(order_date = '2023-05-05', amount, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY 1 ORDER BY 1; 2-3) SELECT user_id, MAX(IF(order_date = '2023-05-01', 1, 0)) AS `2023-05-01`, MAX(IF(order_date = '2023-05-02', 1, 0)) AS `2023-05-02`, MAX(IF(order_date = '2023-05-03', 1, 0)) AS `2023-05-03`, MAX(IF(order_date = '2023-05-04', 1, 0)) AS `2023-05-04`, MAX(IF(order_date = '2023-05-05', 1, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY 1 ORDER BY 1; 2-4) SELECT event_date, event_timestamp, event_name, event_timestamp, user_pseudo_id, MAX(CASE WHEN event_param.key = 'firebase_screen' THEN event_param.value.string_value END) as firebase_screen, MAX(CASE WHEN event_param.key = 'food_id' THEN event_param.value.int_value END) as food_id, MAX(CASE WHEN event_param.key = 'session_id' THEN event_param.value.string_value END) as session_id, FROM advanced.app_logs CROSS JOIN UNNEST(event_params) as event_param WHERE event_date = '2022-08-01' GROUP BY ALL 3) 퍼널 쿼리 연습 문제 WITH main as ( SELECT event_date, concat(event_name,'-', event_param.value.string_value) AS event_name_with_screen, CASE WHEN event_name = 'screen_view' AND event_param.value.string_value = 'welcome' THEN 1 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'home' THEN 2 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'food_category' THEN 3 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'restaurant' THEN 4 WHEN event_name = 'screen_view' AND event_param.value.string_value = 'cart' THEN 5 WHEN event_name = 'click_payment' AND event_param.value.string_value = 'cart' THEN 6 END AS step_num, count(distinct user_pseudo_id) AS cnt FROM advanced.app_logs CROSS JOIN UNNEST(event_params) as event_param WHERE event_date between '2022-08-01' AND '2022-08-18' AND event_param.key = 'firebase_screen' AND event_name IN ("screen_view",'click_payment') GROUP BY 1,2,3 HAVING step_num IS NOT NULL ) SELECT event_date, SUM(IF(step_num = 1, cnt, 0)) AS `screen_view-welcome`, SUM(IF(step_num = 2, cnt, 0)) AS `screen_view-home`, SUM(IF(step_num = 3, cnt, 0)) AS `screen_view-food_category`, SUM(IF(step_num = 4, cnt, 0)) AS `screen_view-restaurant`, SUM(IF(step_num = 5, cnt, 0)) AS `screen_view-cart`, SUM(IF(step_num = 6, cnt, 0)) AS `click_payment-cart` FROM main GROUP BY 1 ORDER BY event_date
연습 문제 (1) Array, Struct -- 1) array_exercises 테이블에서 각 영화(title)별로 장르(genres)를 UNNEST해서 보여주세요 SELECT title, genre # genres 아님 FROM `advanced.array_exercises` CROSS JOIN UNNEST(genres) AS genre 처음에 'title'을 기준으로 묶여 있길래 UNNEST의 요소로 'title'을 넣으려 함 → ERROR 생각해보니 CROSS JOIN이 목적이므로 개별 값을 가지는 'genres'를 기준으로 UNNEST -- 2) array_exercises 테이블에서 각 영화(title)별로 배우(actor)와 배역(character)을 보여주세요. 배우와 배역은 별도의 컬럼으로 나와야 합니다 SELECT title, actor, character FROM `advanced.array_exercises`, UNNEST(actors) CROSS JOIN 대신 ','를 통해 UNNEST를 시도해 봄 -- 3) array_exercises 테이블에서 각 영화(title)별로 배우(actor), 배역(character), 장르 (genre)를 출력하세요. -- 한 Row에 배우, 배역, 장르가 모두 표시되어야 합니다 SELECT title, ae2.actor, ae2.character, genre FROM ( SELECT title, actor.actor, actor.character, genres FROM `advanced.array_exercises` AS ae, UNNEST(actors) AS actor ) AS ae2, UNNEST(genres) AS genre -- 강의 코드 SELECT title, actor.actor, actor.character, genre FROM `advanced.array_exercises` AS ae, UNNEST(actors) AS actor, UNNEST(genres) AS genre UNNEST 두번해야해서 서브쿼리로 해결하려 시도 → 서브 쿼리 안하고 UNNEST 두번 사용 가능 실행 순서 : FROM → JOIN → SELECT cmd + D : 다음 해당 항목 같이 선택 → 반복되는 단어 쉽게 수정 가능 -- 4) 앱 로그 데이터(app_logs)의 배열을 풀어주세요 SELECT user_id, event_date, event_name, user_pseudo_id, EV.key, EV.value.string_value, EV.value.int_value FROM `advanced.app_logs` AS al, UNNEST(event_params) AS EV -- 강의 코드 SELECT event_date, event_timestamp, event_name, event_param.key AS key, event_param.value AS value, user_id FROM `advanced.app_logs`, UNNEST(event_params) AS event_param WHERE event_date = "2022-08-01" WHERE에 조건을 넣어 연산량 낮출 수 있음 event_params로 UNNEST했을때 value값만 사용해도 string, int 둘다 표시됨 (2) PIVOT parquet : 대용량 데이터를 효율적으로 저장하고 처리하기 위해 설계된 컬럼 기반의 저장 형식 공통 사항 : 행과 열에 대한 정의가 한번에 떠오르지 않았음 -- 1) orders 테이블에서 유저(user_id)별로 주문 금액(amount)의 합계를 PIVOT해주세요. -- 날짜(order_date)를 행(Row)으로, user_id를 열(Column)으로 만들어야 합니다 SELECT order_date, SUM(IF(user_id=1, amount, 0)) AS user_1, SUM(IF(user_id=2, amount, 0)) AS user_2, SUM(IF(user_id=3, amount, 0)) AS user_3, FROM `advanced.orders` GROUP BY order_date ORDER BY order_date NULL과 0은 다르다 서브쿼리 이용한 방법도 있음(집계 후 PIVOT) -- 2) orders 테이블에서 날짜(order_date)별로 유저들의 주문 금액(amount)의 합계를 PIVOT 해주세요. -- user_id를 행(Row)으로, order_date를 열(Column)으로 만들어야 합니다 SELECT user_id, SUM(IF(order_date="2023-05-01", amount, 0)) AS `2023-05-01`, SUM(IF(order_date="2023-05-02", amount, 0)) AS `2023-05-02`, SUM(IF(order_date="2023-05-03", amount, 0)) AS `2023-05-03`, SUM(IF(order_date="2023-05-04", amount, 0)) AS `2023-05-04`, SUM(IF(order_date="2023-05-05", amount, 0)) AS `2023-05-05`, FROM `advanced.orders` GROUP BY user_id AS에서 “ ”(따옴표) 대신 (백틱) 사용 ANY_VALUE : 그룹화 할 대상 중에 임의의 값을 선택한다(NULL 제외) 따라서 나머지 값들이 NULL이거나 값이 확정적일 때 사용 -- 3) orders 테이블에서 사용자(user_id)별, 날짜(order_date)별로 주문이 있다면 1, 없다면 0으로 PIVOT 해주세요. -- user_id를 행(Row)으로, order_date를 열(Column)로 만들고 주문을 많이 해도 1로 처리합니다 SELECT user_id, MAX(IF(order_date="2023-05-01", 1, 0)) AS `2023-05-01`, MAX(IF(order_date="2023-05-02", 1, 0)) AS `2023-05-02`, MAX(IF(order_date="2023-05-03", 1, 0)) AS `2023-05-03`, MAX(IF(order_date="2023-05-04", 1, 0)) AS `2023-05-04`, MAX(IF(order_date="2023-05-05", 1, 0)) AS `2023-05-05`, FROM `advanced.orders` GROUP BY user_id 조건문에서 행 별로 주문 있으면 1, 없으면 0 설정한 뒤 MAX 조건 걸어줌 → 최종적으로 값이 있으면 1 횟수일 경우에는 SUM -- user_id = 32888이 카트 추가하기(click_cart)를 누를때 어떤 음식(food_id)을 담았나요? => 쿼리 작성이 어려움 -- => key를 Column으로 두고, string_value나 int_value를 Column의 값으로 설정하는 것이 필요 SELECT user_id, event_date, event_name, event_timestamp, ANY_VALUE(IF(event_param.key="firebase_screen", event_param.value.string_value, NULL)) AS `firebase_screen`, ANY_VALUE(IF(event_param.key="food_id", event_param.value.int_value, NULL)) AS `food_id`, ANY_VALUE(IF(event_param.key="session_id", event_param.value.string_value, NULL)) AS `session_id`, FROM `advanced.app_logs`, UNNEST(event_params) AS event_param WHERE (event_date = "2022-08-01") AND (event_name = "click_cart") AND (user_id = 32888) # 선택 사항 GROUP BY user_id, event_date, event_name, event_timestamp 문제를 봤을 때 문제가 원하는게 무엇인지 한번에 파악되지 않았음 32888의 click cart 행위에만 집중하는 것으로 판단 GROUP BY ALL 을 통해 한번에 해결 가능 (3) 퍼널 쿼리 WITH base AS ( SELECT user_id, user_pseudo_id, event_date, event_name, event_timestamp, platform, ANY_VALUE(IF(event_param.key="firebase_screen", event_param.value.string_value, NULL)) AS `firebase_screen`, ANY_VALUE(IF(event_param.key="food_id", event_param.value.int_value, NULL)) AS `food_id`, ANY_VALUE(IF(event_param.key="session_id", event_param.value.string_value, NULL)) AS `session_id`, FROM `advanced.app_logs`, UNNEST(event_params) AS event_param WHERE event_date BETWEEN "2022-08-01" AND "2022-08-18" GROUP BY ALL ) event_name과 event_params가 연결되어야 하므로 우선 UNNEST 필요하다고 생각함 → 이전에 사용했던 쿼리문 그대로 사용 후 WITH 하지만 이후 과정에서 CONCAT 함수를 떠올리지 못해 진행이 불가했음 ), concat_event_screen AS ( SELECT * EXCEPT(event_name, firebase_screen, event_timestamp), CONCAT(event_name, "-", firebase_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM base ) 이후에 concat_event_screen이라는 이름으로 테이블 재가공 해줌 CONCAT을 통해 event_name-firebase-screen event_timestamp 알아보기 쉽게 바꿔준 후 제거 SELECT event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM concat_event_screen GROUP BY ALL HAVING step_number IS NOT NULL # CASE-WHEN에서 포함되지 않는 행위는 제거 CASE-WHEN 이용해서 step_number 컬럼 만들어줌 COUNT + DISTINC 이용해 해당 퍼널에 진입한 고유 유저 수 세주기 퍼널이 아직 익숙하지 않아 혼자서 해결할 수는 없었음 +) 일자별 SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM concat_event_screen GROUP BY ALL HAVING step_number IS NOT NULL # CASE-WHEN에서 포함되지 않는 행위는 제거 ORDER BY event_date 간단한 EDA 지금까지 배운 것을 바탕으로 간단한 데이터 탐색 및 분석 행 개수 → 731873행 2022-08-01(월) ~ 2023-01-20(금) 의 데이터 user_id 고유 개수 → 49678 pseudo_user_id 고유 개수 → 52823 event_params → 22개 아래 표는 전체 기간에 대한 각 event_params별 개수 총합(내림차순) -> 개수가 같은 항목들이 존재 -> 앱 작동 흐름에 대해 알 필요 있어 보임 event_date에 따른 pseudo_user_id 고유 개수 그래프 -> 8월부터 10월 중순까지는 이용자수가 늘어나는 추세 -> 이후 안정기 들어서면서 일정한 주기로 반복되는 형태 느낀점 보통 데이터 분석 프로젝트를 하면 Python이나 R을 통해 진행했기에 아직 쿼리문이 생소함 머릿속으로는 대충 어떤 식으로 데이터를 건드려야겠다는 생각이 들긴 하지만, 표현이 잘 안되는 경우가 많아서 까다로웠던 것 같음 업무 경험이 없는 입장에서 퍼널 분석 같은 것들은 실제로 해본적이 없는데, 비교적 이해하기 쉽게 알려주신 것 같음
"1-6. [응용] 폴더에 있는 한글 파일을 모두 열기" 관련입니다. 일단 일코님의 설명대로 한 두 번 그대로 성공하고 나면, 강의 내용이 잘 이해가 됩니다. 하지만 초반에는 저 같은 왕초보의 경우 그대로 결과가 나타나지 않거나 실습 조건이 동일하게 마련되지 않으면 헤매게 됩니다. ■ 개선의견 1 이 강의에서는 1.hwp ~ 100.hwp 파일이 들어 있는 "반복작업" 폴더가 있다고 가정하고 실습을 진행하는데요. 물론, 1.hwp 파일을 다운로드 가능하게 되어 있지만.. 1.hwp ~ 100.hwp 파일을 다 만들어 내는 것이 선행되어야 그대로 실습이 가능한데, 그 파일을 만드는 것은 강의 초반이 아니라 후반에 배치되어 있습니다. 제 의견은, 1.hwp ~ 100.hwp 파일을 만들어 내는 부분을 앞에 배치하고, 설명에서는 "이 코드는 아직 안배운 내용이 포함 되므로, 이대로 실습해서 1.hwp ~ 100.hwp 를 만드는 게 부담스러운 학습자는 이 부분을 SKIP하고 진행하세요."라고 한다던가, 아울러, "만약 SKIP하고 진행하실 분들은 1.hwp ~ 100.hwp 파일이 들어 있는 압축파일(zip)을 다운로드 받아서 진행하시면 됩니다."라고 안내하면서, 해당 압축파일의 다운로드도 제공해 주시는 게 어떨까 합니다. ■ 개선의견 2 또 하나는, 작업 디렉토리의 강제 설정을 위한 코드 예시도 추가로 설명에 넣어 주셔도 좋을 거 같습니다. os.chdir(r"C:\Users\user\Desktop\반복작업") 파이참으로 실습 시 작업 디렉토리는 '반복작업' 폴더가 아닌 경우가 대부분으로 왕초보는 요걸로 또 막힐 수 있습니다. ■ 마치는 글 이미 잘 만들어 주신 강의이지만 왕초보의 더 매끄러운 이해를 위한 제안을 드리는 것이니, 꼭 반영하지는 않으셔도 되지만.. 왕초보는 이런 어려움도 있구나.. 정도로 이해해 주시면 감사하겠습니다. 간단한 것도 실행되면 큰 즐거움을 느끼면서 틈틈이 강의 따라하고 있습니다. 감사합니다.
연습문제 (1) ARRAY, STRUCT -- 1) array_exercises 테이블에서 각 영화(title)별로 장르(genres)를 UNNEST해서 보여주세요 # 쿼리를 작성하는 목표, 확인할 지표 : 평면화 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : array_exercises # Join KEY : # 데이터 특징 : SELECT title, genre FROM advanced.array_exercises CROSS JOIN UNNEST(genres) AS genre; -- 2) array_exercises 테이블에서 각 영화(title)별로 배우(actor)와 배역(character)을 보여주세요. 배우와 배역은 별도의 컬럼으로 나와야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : 영화별 배우와 배역 평면화 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : array_exercises # Join KEY : # 데이터 특징 : 배우와 배역은 별도의 컬럼으로 나와야 합니다 SELECT title, actor.actor, actor.character FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS actor; -- 3) array_exercises 테이블에서 각 영화(title)별로 배우(actor), 배역(character), 장르 (genre)를 출력하세요. 한 Row에 배우, 배역, 장르가 모두 표시되어야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : 배우, 배역, 장르 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : array_exercises # Join KEY : # 데이터 특징 : 한 Row에 배우, 배역, 장르가 모두 표시되어야 함 SELECT title, actor.actor, actor.character, genre FROM advanced.array_exercises CROSS JOIN UNNEST(actors) AS actor CROSS JOIN UNNEST(genres) AS genre; -- 4) 앱 로그 데이터(app_logs)의 배열을 풀어주세요 # 쿼리를 작성하는 목표, 확인할 지표 : 앱 로그 데이터 평면화 # 쿼리 계산 방법 : UNNEST # 데이터의 기간 : # 사용할 테이블 : app_logs # Join KEY : # 데이터 특징 : event_params안에 ARRAY와 STRUCT 구조가 공존하고 있고 값이 string_value와 int_value 두 종류로 나뉨 확인 필요!! SELECT user_id, event_date, event_name, user_pseudo_id, event_param.key, event_param.value.string_value, event_param.value.int_value FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS event_param WHERE event_date = "2022-08-01"; (2) PIVOT -- 1) orders 테이블에서 유저(user_id)별로 주문 금액(amount)의 합계를 PIVOT해주세요. 날짜(order_date)를 행(Row)으로, user_id를 열(Column)으로 만들어야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : # 쿼리 계산 방법 : MAX, IF, GROUP BY # 데이터의 기간 : # 사용할 테이블 : orders # Join KEY : # 데이터 특징 : SELECT order_date, SUM(IF(user_id = 1, amount, 0)) AS user_1, SUM(IF(user_id = 2, amount, 0)) AS user_2, SUM(IF(user_id = 3, amount, 0)) AS user_3, FROM advanced.orders GROUP BY ALL ORDER BY order_date; -- 2) orders 테이블에서 날짜(order_date)별로 유저들의 주문 금액(amount)의 합계를 PIVOT 해주세요. user_id를 행(Row)으로, order_date를 열(Column)으로 만들어야 합니다 # 쿼리를 작성하는 목표, 확인할 지표 : # 쿼리 계산 방법 : SUM, IF, GROUP BY # 데이터의 기간 : # 사용할 테이블 : orders # Join KEY : # 데이터 특징 : SELECT user_id, SUM(IF(order_date = "2023-05-01", amount, 0)) AS `2023-05-01`, SUM(IF(order_date = "2023-05-02", amount, 0)) AS `2023-05-02`, SUM(IF(order_date = "2023-05-03", amount, 0)) AS `2023-05-03`, SUM(IF(order_date = "2023-05-04", amount, 0)) AS `2023-05-04`, SUM(IF(order_date = "2023-05-05", amount, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY ALL ORDER BY user_id; -- 3) orders 테이블에서 사용자(user_id)별, 날짜(order_date)별로 주문이 있다면 1, 없다면 0으로 PIVOT 해주세요. user_id를 행(Row)으로, order_date를 열(Column)로 만들고 주문을 많이 해도 1로 처리합니다 # 쿼리를 작성하는 목표, 확인할 지표 : # 쿼리 계산 방법 : MAX, IF, GROUP BY # 데이터의 기간 : # 사용할 테이블 : orders # Join KEY : # 데이터 특징 : SELECT user_id, MAX(IF(order_date = "2023-05-01", 1, 0)) AS `2023-05-01`, MAX(IF(order_date = "2023-05-02", 1, 0)) AS `2023-05-02`, MAX(IF(order_date = "2023-05-03", 1, 0)) AS `2023-05-03`, MAX(IF(order_date = "2023-05-04", 1, 0)) AS `2023-05-04`, MAX(IF(order_date = "2023-05-05", 1, 0)) AS `2023-05-05` FROM advanced.orders GROUP BY ALL ORDER BY user_id; -- 연습문제 4) app_log를 pivot하기 # 쿼리를 작성하는 목표, 확인할 지표 : app_log 데이터 PIVOT 테이블로 변경 # 쿼리 계산 방법 : UNNEST, MAX, IF, GROUP BY # 데이터의 기간 : 2022-08-01 # 사용할 테이블 : app_logs # Join KEY : # 데이터 특징 : event_params안에 ARRAY와 STRUCT 구조가 공존하고 있고 값이 string_value와 int_value 두 종류로 나뉨 확인 필요!! WITH base AS( SELECT user_id, event_date, event_name, event_timestamp, user_pseudo_id, MAX(if(event_param.key = "firebase_screen", event_param.value.string_value, NULL)) AS firebase_screen, MAX(if(event_param.key ="food_id", event_param.value.int_value, NULL)) AS food_id, MAX(if(event_param.key ="session_id", event_param.value.string_value, NULL)) AS session_id FROM avdanced.app_logs CROSS JOIN UNNEST (event_params) AS event_param WHERE event_date ='2022-08-01' GROUP BY ALL ) SELECT event_date, COUNT(user_id) AS cnt FROM base WHERE event_name = 'click_cart' GROUP BY ALL; (3) 퍼널 ( Funnel ) # 쿼리를 작성하는 목표, 확인할 지표 : screen_view-welcome, screen_view-home, screen_view-food_category, screen_view-restaurant, screen_view-cart, click_payment-cart 순서대로 step_number를 지정하고 퍼널 분석하기 # 쿼리 계산 방법 : MAX, IF, UNNEST, CASE WHEN # 데이터의 기간 : 2022-08-01 ~ 2022-08-18 # 사용할 테이블 : app_logs # Join KEY : # 데이터 특징 : event_params안에 ARRAY와 STRUCT 구조가 공존하고 있고 값이 string_value와 int_value 두 종류로 나뉨 확인 필요!! WITH base AS (SELECT event_date, event_timestamp, event_name, user_id, user_pseudo_id, platform, MAX(IF(event_param.key = "firebase_screen", event_param.value.string_value, NULL)) AS fire_screen, -- MAX(IF(event_param.key = "food_id", event_param.value.int_value, NULL)) AS food_id, MAX(IF(event_param.key = "session_id", event_param.value.string_value, NULL)) AS session_id FROM advanced.app_logs CROSS JOIN UNNEST(event_params) AS event_param WHERE event_date BETWEEN "2022-08-01" AND "2022-08-18" GROUP BY ALL ), fiter_event_and_concat_event_and_screen AS ( -- event_name + screen (필요한 이벤트만 WHERE 조건에 걸어서 사용) SELECT * EXCEPT(event_name, fire_screen, event_timestamp), CONCAT(event_name, "-", fire_screen) AS event_name_with_screen, DATETIME(TIMESTAMP_MICROS(event_timestamp), 'Asia/Seoul') AS event_datetime FROM base WHERE event_name IN ("screen_view", "click_payment") ) -- step_number + COUNT -- step_number : CASE WHEN을 사용해 숫자 지정 SELECT event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM fiter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL WHERE user_pseudo_id = "1350836585.3421064109" -- 일자별 SELECT event_date, event_name_with_screen, CASE WHEN event_name_with_screen = "screen_view-welcome" THEN 1 WHEN event_name_with_screen = "screen_view-home" THEN 2 WHEN event_name_with_screen = "screen_view-food_category" THEN 3 WHEN event_name_with_screen = "screen_view-restaurant" THEN 4 WHEN event_name_with_screen = "screen_view-cart" THEN 5 WHEN event_name_with_screen = "click_payment-cart" THEN 6 ELSE NULL END AS step_number, COUNT(DISTINCT user_pseudo_id) AS cnt FROM fiter_event_and_concat_event_and_screen GROUP BY ALL HAVING step_number IS NOT NULL ORDER BY event_date; 배운점 ARRAY와 STRUCT 라는 조금은 생소할 수 있는 데이터 타입과 이를 어떻게 하면 평면화로 풀고 어떻게 데이터를 처리할 수 있을지를 조금은 알 수 있었고 BigQuery로 생각보다 많은 부분을 할 수 있구나 생각이 들면서 이를 프로젝트에 연결시키면 어떨까 하는 재밌는 고민이 생긴거 같다 BIgQuery를 배우고 싶은데 어떤 데이터로 어떻게 다뤄야 할지 막막했던 찰라에 많은 것을 배울 수 있던 1주차 였다
[리뉴얼] 파이썬입문과 크롤링기초 부트캠프 [파이썬, 웹, 데이터 이해 기본까지] (업데이트)
반복문과 다양한 데이터 구조 활용2에서 58번 문제 질문 있습니다. 이렇게 작성해도 되나요? data = {'environment': ['환경','x'], 'company': ['회사','o'], 'government': ['정부, 정치','x'], 'face': ['얼굴','x']} eng = input("영어 단어를 입력하세요 : ") for item in data.keys() : if eng == item and data[item][1] == 'x' : data[item][1] = 'o' if data[item][1] == 'x' : print(item)