파이톤으로 처음부터 집계

개술


이 글은 나Data Science from Scratch by Joel Grus가 보도한 다섯 번째 장이다.
주의해야 할 것은 본고에서 언급한 모든 내용은 NumPystatistics module in Python 같은 라이브러리에서 더욱 편리하고 효율적으로 완성할 수 있다는 것이다.
내가 보기에 이 책과 이 글의 주요 가치는 파이톤 원어를 어떻게 사용하는지 배우는 것을 강조하여 처음부터 도구를 구축하는 데 있다.다음은 시각 미리보기입니다.

구체적으로 말하면, 우리는 파이톤 언어의 특정한 기능을 어떻게 사용하는지, 그리고 우리가 이전 글에서 구축한 함수를 이용하여 데이터와 데이터의 내관계 (통계) 를 설명하는 도구를 구축하는지 연구할 것이다.
나는 이것이 매우 멋있다고 생각한다.허락해주셨으면 좋겠습니다.

샘플 데이터


이 장에서는 데이터 과학자인 소셜네트워크서비스인 DataScienster의 새로운 데이터 과학자에 대한 이야기를 이어가며 이 소셜네트워크서비스에 친구가 얼마나 있는지 묘사하는 일을 한다.우리는 두 개lists가 합작해야 한다.우리는 먼저 float를 사용한 다음에 다시 사용할 것이다num_friends.
나는 이 문장이 독립적이기를 바란다. 이를 위해 우리는 평균 수준daily_minutes보다 높은 문장list을 읽어야 한다.또 다른 방법은 책에서github repo (statistics.py)에서 데이터를 직접 얻는 것이다.
num_friends = [100.0,49,41,40,25,21,21,19,19,18,18,16,15,15,15,15,14,14,13,13,13,13,12,12,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]

daily_minutes = [1,68.77,51.25,52.08,38.36,44.54,57.13,51.4,41.42,31.22,34.76,54.01,38.79,47.59,49.1,27.66,41.03,36.73,48.65,28.12,46.62,35.57,32.98,35,26.07,23.77,39.73,40.57,31.65,31.21,36.32,20.45,21.93,26.02,27.34,23.49,46.94,30.5,33.8,24.23,21.4,27.94,32.24,40.57,25.07,19.42,22.39,18.42,46.96,23.72,26.41,26.97,36.76,40.32,35.02,29.47,30.2,31,38.11,38.18,36.31,21.03,30.86,36.07,28.66,29.08,37.28,15.28,24.17,22.31,30.17,25.53,19.85,35.37,44.6,17.23,13.47,26.33,35.02,32.09,24.81,19.33,28.77,24.26,31.98,25.73,24.86,16.28,34.51,15.23,39.72,40.8,26.06,35.76,34.76,16.13,44.04,18.03,19.65,32.62,35.59,39.43,14.18,35.24,40.13,41.82,35.45,36.07,43.67,24.61,20.9,21.9,18.79,27.61,27.21,26.61,29.77,20.59,27.53,13.82,33.2,25,33.1,36.65,18.63,14.87,22.2,36.81,25.53,24.62,26.25,18.21,28.08,19.42,29.79,32.8,35.99,28.32,27.79,35.88,29.06,36.28,14.1,36.63,37.49,26.9,18.58,38.48,24.48,18.95,33.55,14.24,29.04,32.51,25.63,22.22,19,32.73,15.16,13.9,27.2,32.01,29.27,33,13.74,20.42,27.32,18.23,35.35,28.48,9.08,24.62,20.12,35.26,19.92,31.02,16.49,12.16,30.7,31.22,34.65,13.13,27.51,33.2,31.57,14.1,33.42,17.44,10.12,24.42,9.82,23.39,30.93,15.03,21.67,31.09,33.29,22.61,26.89,23.48,8.38,27.81,32.35,23.84]

daily_hours = [dm / 60 for dm in daily_minutes]

묘사

floats 목록은 한 사람의'친구 수'를 대표하는 숫자 목록이다. 예를 들어 한 사람이 100명의 친구가 있다.우리가 데이터를 묘사하는 첫 번째 일은 100명의 친구, 49명의 친구, 41명의 친구를 그려내는 조형도를 만드는 것이다.
우리는 num_friends에서 Counter를 가져오고 collections를 가져올 것이다.
우리는 matplotlib.pyplot를 사용하여 Counter 목록을 유사num_friends의 대상 맵키로 계수로 변환할 것이다.더 많은 정보를 알고 싶으면 카운터의 이 항목을 참조하세요.
일단 우리가 defaultdict(int) 집합high-performance container datatype을 사용한다면 우리는 Counter과 같은 방법으로 가장 흔히 볼 수 있는 값을 가진 키를 찾을 수 있다.여기서 우리가 가장 흔히 볼 수 있는 다섯 명의 친구는 각각 6, 1, 4, 3, 9이다.
from collections import Counter

import matplotlib.pyplot as plt

friend_counts = Counter(num_friends)

# the five most common values are: 6, 1, 4, 3 and 9 friends
# [(6, 22), (1, 22), (4, 20), (3, 20), (9, 18)]
friend_counts.most_common(5) 
인쇄를 계속하려면 most_common 을 사용하여 friend_counts 을 만들 것입니다. list comprehension 와 0-101 (xs) 사이의 모든 키를 순환시키고 해당하는 값을 출력합니다. (만약 존재한다면)이것은 Y축에서 friends_count까지, 즉 x축이 됩니다.
xs = range(101)                     # x-axis: largest num_friend value is 100
ys = [friend_counts[x] for x in xs] # y-axis
plt.bar(xs, ys)
plt.axis([0, 101, 0, 25])
plt.title("Histogram of Friend Counts")
plt.xlabel("# of friends")
plt.ylabel("# of people")
plt.show()
다음은 줄거리.너는 한 사람이 100명의 친구가 있는 것을 볼 수 있다.

데이터의 시각화에 관한 더 많은 내용을 읽을 수 있습니다.
또는 우리는 내장된 파이톤 방법으로 간단한 통계 데이터를 생성하여 num_friends,len,min,maxsorted를 설명할 수 있다.
num_points = len(num_friends) # number of data points in num_friends: 204
largest_value = max(num_friends) # largest value in num_friends: 100
smallest_value = min(num_friends) # smallest value in num_friends: 1

sorted_values = sorted(num_friends) # sort the values in ascending order
second_largest_value = sorted_values[-2] # second largest value from the back: 49

중심 경향


한 그룹의 데이터를 설명하는 가장 자주 사용하는 방법은 그 평균값, 즉 모든 값의 합을 값의 개수로 나누는 것이다.참고: 유형 주석은 계속 사용됩니다.내가 보기에, 이것은 네가 더욱 심사숙고한 파이톤 프로그래머가 되는 데 도움이 될 것이다.
from typing import List

def mean(xs: List[float]) -> float:
    return sum(xs) / len(xs)

assert 7.3333 < mean(num_friends) < 7.3334
그러나 균일치가 이상치에 대한 민감성은 유명하기 때문에 통계학자들은 보통 중위수 등 중심 추세의 다른 도량으로 보충한다.중위수는 가장 중간값이기 때문에 데이터 점의 수량이 짝수인지 홀수인지 매우 중요하다.
여기서, 우리는 이 두 가지 상황을 위해 두 개의 사유 함수인 짝수와 홀수 데이터 포인트를 만들어서 중치를 계산할 것이다.우선, 우리는 데이터 값에 대해 정렬을 진행할 것이다.그리고 짝수 값에 대해 우리는 두 개의 중간 값을 찾아서 그것을 분리할 것이다.홀수 개의 값에 대해 우리는 데이터 집합의 길이를 2(즉 50)로 나눈다.
우리의 중치 함수는 사유 함수 _median_even 또는 _median_odd 를 조건부로 되돌려줍니다. 이것은 숫자 목록의 길이가 2로 정제될 수 있는지 여부에 달려 있습니다. (% 2=0)
def _median_even(xs: List[float]) -> float:
    """If len(xs) is even, it's the average of the middle two elements"""
    sorted_xs = sorted(xs)
    hi_midpoint = len(xs) // 2   # e.g. length 4 => hi_midpoint 2
    return (sorted_xs[hi_midpoint - 1] + sorted_xs[hi_midpoint]) / 2

def _median_odd(xs: List[float]) -> float:
    """If len(xs) is odd, its the middle element"""
    return sorted(xs)[len(xs) // 2]

def median(v: List[float]) -> float:
    """Finds the 'middle-most' value of v"""
    return _median_even(v) if len(v) % 2 == 0 else _median_odd(v)

assert median([1,10,2,9,5]) == 5
assert median([1, 9, 2, 10]) == (2 + 9) / 2
중위수는 가장 중간값이기 때문에 데이터의 모든 값에 완전히 의존하지 않는다.예를 들어 우리가 다른 명단num_friends2을 가지고 있는데 그 중 한 명이 10000명의 친구가 있다고 가정하면 이런 변화에 대한 민감성은 중위수보다 평균적으로 훨씬 민감하다.
num_friends2 = [10000.0,49,41,40,25,21,21,19,19,18,18,16,15,15,15,15,14,14
    ,13,13,13,13,12,12,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,9
    ,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7
    ,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5
    ,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3
    ,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1
    ,1,1,1,1,1,1,1,1,1,1,1,1]

mean(num_friends2)   # more sensitive to outliers: 7.333 => 55.86274509803921
median(num_friends2) # less sensitive to outliers: 6.0 => 6.0

quantiles를 사용하여 데이터를 설명할 수도 있습니다."X퍼센트 숫자"를 들을 때마다 100퍼센트에 대한 설명이다.사실상 중위수는 50번째 백분위(그중 50%의 데이터는 이 점 이하, 50%는 이 점 이상)이다.quantile는 0-100 사이의 위치이기 때문에 두 번째 파라미터는 0.0에서 1.0 사이의 부동점이다.우리는 이 부동점수를 목록의 길이에 곱할 것이다.그리고, 우리는 int 을 사용하여 정수 인덱스를 만들 것입니다. 이 인덱스를 사용하여 정렬된 xs의 분위수를 찾을 것입니다.
def quantile(xs: List[float], p: float) -> float:
    """Returns the pth-percentile value in x"""
    p_index = int(p * len(xs))  
    return sorted(xs)[p_index]

assert quantile(num_friends, 0.10) == 1
assert quantile(num_friends, 0.25) == 3
assert quantile(num_friends, 0.75) == 9
assert quantile(num_friends, 0.90) == 13
마지막으로 모드입니다. 가장 흔히 볼 수 있는 값을 볼 수 있습니다.우선, 우리는 목록 매개 변수에 Counter 방법을 사용합니다. 계수기는 dict의 하위 클래스이기 때문에 우리는 values() 등 방법으로 모든 값을 찾을 수 있고 items() 키 값 쌍을 찾을 수 있습니다.
최대 값 (22) 을 찾기 위해 max_count 을 정의한 다음, 함수는 목록 이해를 되돌려줍니다. 최대 계수 (22) 와 관련된 키를 찾기 위해 순환 counts.items() 을 반복합니다.이것은 1과 6으로 22명(모드)에 한 명 또는 여섯 명의 친구가 있다는 것을 의미한다.
def mode(x: List[float]) -> List[float]:
    """Returns a list, since there might be more than one mode"""
    counts = Counter(x)
    max_count = max(counts.values())
    return [x_i for x_i, count in counts.items() if count == max_count]


assert set(mode(num_friends)) == {1, 6}
우리는 이미 num_friends에서 Counter를 사용했기 때문에 friend_counts 방법을 사용해서 같은 결과를 얻을 수 있다.
mode(num_friends) # [6, 1]
friend_counts.most_common(2) # [(6, 22), (1, 22)]

흩어지다


우리 데이터의 중심 추세를 제외하고는 그 전파나 분산도 알고 싶다.이 작업을 수행하는 도구는 most_common(2), data_range, variancestandard deviation입니다.
범위는 간단한 최대치에서 최소치를 빼는 것이다.
방차는 aset of numbers is from their average value의 거리를 측정한다.우리에게는 더 흥미로운 것은 이전에 게시물과 구축된 함수를 빌려 방차 함수를 만드는 방법이 필요하다는 것이다.
만약 위키백과 페이지를 본다면, 방차는 변수와 그 평균치의 제곱 편차이다.
우선, 우리는 interquartile range 함수를 만들어야 한다. 이 함수는 숫자 목록을 가져오고, 목록의 모든 숫자에서 평균 값을 빼야 한다. (이것은 우리에게 평균 값과의 편차를 준다.)
그리고 우리는 de_mean 이 모든 편차를 가질 것이다. 이것은 우리가 모든 값을 취하여 그것들을 자신과 곱하기 (제곱하기) 한 다음에 이 값을 더하고 (목록의 길이를 1로 나누기) 방차를 얻는 것을 의미한다.
돌이켜보면 sum_of_squaressum_of_squares 제품 기능의 특례이다.
# variance

from typing import List

Vector = List[float]

# see vectors.py in chapter 4 for dot and sum_of_squares

def dot(v: Vector, w: Vector) -> float:
    """Computes v_1 * w_1 + ... + v_n * w_n"""
    assert len(v) == len(w), "vectors must be the same length"
    return sum(v_i * w_i for v_i, w_i in zip(v,w))

def sum_of_squares(v: Vector) -> float:
    """Returns v_1 * v_1 + ... + v_n * v_n"""
    return dot(v,v)

def de_mean(xs: List[float]) -> List[float]:
    """Translate xs by subtracting its mean (so the result has mean 0)"""
    x_bar = mean(xs)
    return [x - x_bar for x in xs]

def variance(xs: List[float]) -> float:
    """Almost the average squared deviation from the mean"""
    assert len(xs) >= 2, "variance requires at least two elements"
    n = len(xs)
    deviations = de_mean(xs)
    return sum_of_squares(deviations) / (n - 1)

assert 81.54 < variance(num_friends) < 81.55
방차는 dot개의 편차로 해석하기 어려울 수 있다.예를 들어 우리는 0에서 100 사이의 값을 가지고 있다sum_of_squares.

What does a variance of 81.54 mean?


더 흔히 볼 수 있는 대체 방법은 표준차이다.여기에서, 우리는 파이톤의 num_friends 모듈을 사용하여 방차의 제곱근을 얻는다.
표준 편차는 9.03이고 math의 평균치는 7.3이며 7+9=16 또는 7-9(친구 0명)보다 낮은 친구는 여전히 평균치의 표준 편차 범위 내에 있다는 것을 우리는 알고 있다.우리는 운행num_friends을 통해 대다수의 사람들이 평균치의 표준 편차 범위 내에 있는지 검사할 수 있다.
다른 한편, 우리는 20명의 친구가 있는 사람이 평균치에서 한 명 이상 차이가 있다는 것을 안다.
import math

def standard_deviation(xs: List[float]) -> float:
    """The standard deviation is the square root of the variance"""
    return math.sqrt(variance(xs))

assert 9.02 < standard_deviation(num_friends) < 9.04
그러나 표준차는 방차의 기초 위에서 방차는 균일치에 의존하기 때문에 우리는 균일치처럼 이상치에 민감할 수 있다는 것을 알고 있다. 우리는 4분위 구간이라고 불리는 다른 방법을 사용할 수 있다. 이것은 중위수를 바탕으로 이상치에 민감하지 않다는 것을 안다.
구체적으로 4분위 범위는 25위와 75위 사이의 차이friend_counts를 검사하는 데 쓰일 수 있다.대부분의 사람들은 대략 여섯 명의 친구가 있을 것이다.
def interquartile_range(xs: List[float]) -> float: 
    """Returns the difference between the 75%-ile and the 25%-ile"""
    return quantile(xs, 0.75) - quantile(xs, 0.25)

assert interquartile_range(num_friends) == 6
기왕 우리가 하나의 데이터 목록만 묘사한 이상, 우리는 두 데이터 원본 간의 잠재적인 관계를 보고 싶다.예를 들어 DataScienster 소셜네트워크서비스(SNS)에 걸리는 시간이 한 사람이 가진 친구 수와 관련이 있다는 가설이 있을 수 있다.
이어서 우리는 협방차와 관련성을 검사할 것이다.

상관성


만약에 방차가 한 조의 숫자가 그 평균치에서 벗어난 정도(즉, 윗글num_friends 참조)이라면 협방차 도량은 두 조의 숫자가 그 평균치에서 벗어난 정도이다.그들의 생각은 공통된 변화량이 같으면 관련이 있을 수도 있다는 것이다.
여기서 우리는 게시물에서 개발한de_mean 생산 함수를 빌려 쓸 것이다.
그 밖에 우리는 dotnum_friends 그리고 daily_minutes 사이에 관계가 있는지 검사할 것이다(상기 참조).
def covariance(xs: List[float], ys: List[float]) -> float:
    assert len(xs) == len(ys), "xs and ys must have same number of elements"
    return dot(de_mean(xs), de_mean(ys)) / (len(xs) - 1)

assert 22.42 < covariance(num_friends, daily_minutes) < 22.43
assert 22.42 / 60 < covariance(num_friends, daily_hours) < 22.43 / 60
방차와 마찬가지로 협방차에 대해서도 비슷한 비판을 할 수 있으니, 너는 반드시 추가 절차를 취해 그것을 해석해야 한다.예를 들어 daily_hoursnum_friends의 합방차는 22.43이다.

What does that mean? Is that considered a strong relationship?


보다 직관적인 평가 기준은 관련성이다.
def correlation(xs: List[float], ys: List[float]) -> float:
    """Measures how much xs and ys vary in tandem about their means"""
    stdev_x = standard_deviation(xs)
    stdev_y = standard_deviation(ys)
    if stdev_x > 0 and stdev_y > 0:
        return covariance(xs,ys) / stdev_x / stdev_y
    else:
        return 0 # if no variation, correlation is zero

assert 0.24 < correlation(num_friends, daily_minutes) < 0.25
assert 0.24 < correlation(num_friends, daily_hours) < 0.25
두 입력 변수의 표준 편차를 구분함으로써 관련성은 항상 -1(완벽(반)관련성)과 1(완벽관련성) 사이에 있다.0.24의 관련성은 상대적으로 약한 관련성이다(약, 중, 강한 관련성은 데이터의 상하문에 달려 있지만).
기억해야 할 것은 샘슨 패러다임이나 세 번째 혼동 변수를 고려할 때 두 변수 간의 관계가 변화하는 것이다.그 밖에 우리는 이 케케묵은 말(이것은 원인이 있는 케케묵은 말)을 기억해야 한다. 관련성은 인과관계를 의미하지 않는다.

요약


우리는 지금 5장만 이야기했다. 우리는 우리가 현재 어떻게 도구를 구축하는지 이해하기 시작할 수 있다. 이따가 우리는 이 도구들을 사용할 것이다.다음은 우리가 이 글에서 토론한 내용의 시각적 정리와 그 내용이 이전의 글과 어떻게 연결되는지, 즉python 속성 과정: 참조, 등등이다.

이 게시물은 나의 이 책에 대한 보도를 계속한다.

데이터 과학, 머신러닝, R, 파이톤, SQL 등에 관한 더 많은 내용.

좋은 웹페이지 즐겨찾기