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 등)을 어떻게 참조 할 수 있습니까?
정확한 코드는 수행하려는 각 열에 따라 다르지만 map
및 apply
함수 를 사용하는 것이 좋습니다 . 경우에 따라 기존 열을 사용하여 직접 계산할 수 있습니다. 열이 팬더 시리즈 객체이기 때문에 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과 같은 연산을 사용해야하는 경우 apply
with 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
Hopefully that gives you some idea of how to proceed.
Edit: to compare rows against neighboring rows, the simplest approach is to slice the columns you want to compare, leaving off the beginning/end, and then compare the resulting slices. For instance, this will tell you for which rows the element in column A is less than the next row's element in column C:
d['A'][:-1] < d['C'][1:]
and this does it the other way, telling you which rows have A less than the preceding row's C:
d['A'][1:] < d['C'][:-1]
Doing ['A"][:-1]
slices off the last element of column A, and doing ['C'][1:]
slices off the first element of column C, so when you line these two up and compare them, you're comparing each element in A with the C from the following row.
You could have is_hammer
in terms of row["Open"]
etc. as follows
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)
Then you can use map:
df["isHammer"] = map(is_hammer, df["Open"], df["Low"], df["Close"], df["High"])
For the second part of your question, you can also use shift
, for example:
df['t-1'] = df['t'].shift(1)
t-1
would then contain the values from t one row above.
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.shift.html
The first four functions you list will work on vectors as well, with the exception that lower_wick needs to be adapted. Something like this,
def lower_wick_vec(o, l, c):
min_oc = numpy.where(o > c, c, o)
return min_oc - l
where o, l and c are vectors. You could do it this way instead which just takes the df as input and avoid using numpy, although it will be much slower:
def lower_wick_df(df):
min_oc = df[['Open', 'Close']].min(axis=1)
return min_oc - l
The other three will work on columns or vectors just as they are. Then you can finish off with
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
Bit operators can perform set logic on boolean vectors, &
for and
, |
for or
etc. This is enough to completely vectorize the sample calculations you gave and should be relatively fast. You could probably speed up even more by temporarily working with the numpy arrays underlying the data while performing these calculations.
For the second part, I would recommend introducing a column indicating the pattern for each row and writing a family of functions which deal with each pattern. Then groupby the pattern and apply the appropriate function to each group.
참고URL : https://stackoverflow.com/questions/12376863/adding-calculated-columns-to-a-dataframe-in-pandas
'Programing' 카테고리의 다른 글
Android의 INSTALL_FAILED_MISSING_SHARED_LIBRARY 오류 (0) | 2020.10.17 |
---|---|
해시 가능, 불변 (0) | 2020.10.17 |
Spring Boot Rest Controller 다른 HTTP 상태 코드를 반환하는 방법은 무엇입니까? (0) | 2020.10.17 |
PHP : 클래스 함수를 콜백으로 사용하는 방법 (0) | 2020.10.17 |
총알은 어디에서 왔습니까? (0) | 2020.10.17 |