[python] Pandas의 데이터 프레임에 계산 된 열 추가

CSV에서 Pandas 데이터 프레임으로 파싱하고 15 분 막대로 다시 샘플링 한 OHLC 가격 데이터 세트가 있습니다.

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 500047 entries, 1998-05-04 04:45:00 to 2012-08-07 00:15:00
Freq: 15T
Data columns:
Close    363152  non-null values
High     363152  non-null values
Low      363152  non-null values
Open     363152  non-null values
dtypes: float64(4)

기간 범위 (HL)와 같은 간단한 열로 시작하여 부울을 추가하여 정의 할 가격 패턴 (예 : 해머 캔들 패턴)의 발생을 나타내는 다양한 계산 열을 추가하고 싶습니다.

def closed_in_top_half_of_range(h,l,c):
    return c > l + (h-l)/2

def lower_wick(o,l,c):
    return min(o,c)-l

def real_body(o,c):
    return abs(c-o)

def lower_wick_at_least_twice_real_body(o,l,c):
    return lower_wick(o,l,c) >= 2 * real_body(o,c)

def is_hammer(row):
    return lower_wick_at_least_twice_real_body(row["Open"],row["Low"],row["Close"]) \
    and closed_in_top_half_of_range(row["High"],row["Low"],row["Close"])

기본 문제 : 함수를 열에 매핑하는 방법, 특히 둘 이상의 다른 열이나 전체 행을 참조하고 싶은 곳은 무엇입니까?

이 게시물 에서는 단일 소스 열에서 두 개의 계산 된 열을 추가하는 방법을 다룹니다.

그리고 약간 더 고급 : 하나 이상의 막대 (T)를 참조하여 결정되는 가격 패턴의 경우 함수 정의 내에서 다른 행 (예 : T-1, T-2 등)을 어떻게 참조 할 수 있습니까?



답변

정확한 코드는 수행하려는 각 열에 따라 다르지만 mapapply함수 를 사용하는 것이 좋습니다 . 경우에 따라 기존 열을 사용하여 직접 계산할 수 있습니다. 열이 팬더 시리즈 객체이기 때문에 Numpy 배열로도 작동하며 일반적인 수학 연산에 대해 자동으로 요소별로 작동합니다.

>>> d
    A   B  C
0  11  13  5
1   6   7  4
2   8   3  6
3   4   8  7
4   0   1  7
>>> (d.A + d.B) / d.C
0    4.800000
1    3.250000
2    1.833333
3    1.714286
4    0.142857
>>> d.A > d.C
0     True
1     True
2     True
3    False
4    False

행 내에서 max 및 min과 같은 연산을 사용해야하는 경우 applywith axis=1를 사용 하여 원하는 함수를 각 행에 적용 할 수 있습니다 . 다음은 min(A, B)-C“낮은 심지”처럼 보이는를 계산하는 예입니다 .

>>> d.apply(lambda row: min([row['A'], row['B']])-row['C'], axis=1)
0    6
1    2
2   -3
3   -3
4   -7

진행 방법에 대한 아이디어를 얻을 수 있기를 바랍니다.

편집 : 행을 인접 행과 비교하는 가장 간단한 방법은 비교하려는 열을 분할하고 시작 / 끝을 제외한 다음 결과 조각을 비교하는 것입니다. 예를 들어 A 열의 요소가 C 열의 다음 행 요소보다 작은 행을 알려줍니다.

d['A'][:-1] < d['C'][1:]

그리고 이것은 반대로 A가 이전 행의 C보다 작은 행을 알려줍니다.

d['A'][1:] < d['C'][:-1]

이렇게 ['A"][:-1]열 A의 마지막 요소 떨어져 조각을하고,하고 ['C'][1:]다음 행에서 C와 A의 각 요소를 비교하고,이 두 최대 라인과 그들을 비교 그렇게 할 때, 열 C의 첫 번째 요소 떨어져 조각.


답변

다음과 같은 is_hammer측면에서 가질 수 있습니다 row["Open"].

def is_hammer(rOpen,rLow,rClose,rHigh):
    return lower_wick_at_least_twice_real_body(rOpen,rLow,rClose) \
       and closed_in_top_half_of_range(rHigh,rLow,rClose)

그런 다음지도를 사용할 수 있습니다.

df["isHammer"] = map(is_hammer, df["Open"], df["Low"], df["Close"], df["High"])


답변

질문의 두 번째 부분에는를 사용할 수도 있습니다 shift. 예를 들면 다음과 같습니다.

df['t-1'] = df['t'].shift(1)

t-1 그런 다음 한 행 위에있는 t의 값을 포함합니다.

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.shift.html


답변

나열한 처음 네 개의 함수는 lower_wick을 조정해야하는 경우를 제외하고 벡터에서도 작동합니다. 이 같은,

def lower_wick_vec(o, l, c):
    min_oc = numpy.where(o > c, c, o)
    return min_oc - l

여기서 o, l 및 c는 벡터입니다. 대신 df를 입력으로 취하고 numpy를 사용하지 않는 방법으로 할 수 있습니다.

def lower_wick_df(df):
    min_oc = df[['Open', 'Close']].min(axis=1)
    return min_oc - l

나머지 세 개는 그대로 열 또는 벡터에서 작동합니다. 그런 다음 끝낼 수 있습니다.

def is_hammer(df):
    lw = lower_wick_at_least_twice_real_body(df["Open"], df["Low"], df["Close"])
    cl = closed_in_top_half_of_range(df["High"], df["Low"], df["Close"])
    return cl & lw

비트 연산자, 부울 벡터에 세트 로직을 수행 할 수있는 &위해 and, |위해or 등이 완전히 당신이 준 샘플 계산을 벡터화하기에 충분하고 상대적으로 빠른해야한다. 이러한 계산을 수행하는 동안 데이터의 기본이되는 numpy 배열로 일시적으로 작업하여 더 많은 속도를 높일 수 있습니다.

두 번째 부분에서는 각 행의 패턴을 나타내는 열을 도입하고 각 패턴을 처리하는 함수 제품군을 작성하는 것이 좋습니다. 그런 다음 패턴별로 그룹화하고 각 그룹에 적절한 기능을 적용하십시오.


답변