1. stackoverflow의 유용성이야 다시 강조할 필요도 없지만
데이터 처리 중 만나게 된 settingwithcopywarning.
https://stackoverflow.com/questions/20625582/how-to-deal-with-settingwithcopywarning-in-pandas
2. 구체적인 사례를 보자
CFTC 자료를 가지고 투기세력의 순매수 포지션과 변화를 확인하기 위해 작업 중인데
CFTC 자료는 엑셀 한 시트에 데이터가 다 들어가 있다.
https://www.cftc.gov/MarketReports/CommitmentsofTraders/HistoricalCompressed/index.htm
2-1. CFTC 자료를 읽어들이면
1
|
COT = pd.read_excel("D:\\category\\CFTC\\new\\option\\annual.xls")
|
cs |
아래와 같다.
2-2. 품목을 확인하고 싶다면
1
2
|
for name, group in COT.groupby('Market_and_Exchange_Names'):
print(name)
|
cs |
하면 된다.
2-3. 2020년 파일은 1년 기간이기 때문에 대부분 품목의 갯수는 같지만 과거 자료를 확인해보면
없다 사라지는 경우도 많다.
그래서 변수에 따른 자료 개수를 확인하기 위해
변수별로 그룹화해서 오름차순 정렬해 보면
1
|
COT.groupby("Market_and_Exchange_Names").size().nlargest(20)
|
cs |
내림차순은 smallest() 를 사용한다.
2-4. 위 품목별 투기세력의 순매수 포지션을 구하기 위해서는
1
|
COT['Netlong'] = COT['M_Money_Positions_Long_ALL'] - COT['M_Money_Positions_Short_ALL']
|
cs |
위와 같은 단순 계산으로 새로운 컬럼을 만들면 되고
만약 매수/매도 포지션을 구하기 위해서는 매도 포지션이 0인 경우를 고려해서
1
2
|
COT['M_Money ratio']= np.where(COT['M_Money_Positions_Short_ALL'] == 0, " ", COT['M_Money_Positions_Long_ALL'] / COT['M_Money_Positions_Short_ALL'] )
|
cs |
위와 같이 해주면 된다.
3. 그렇다면 settingwihtcopywarning은 어디서 나타났을까?
순매수 포지션의 전주 변화를 살펴보기 위해
- 사실 이런 단순 계산의 편의성을 위해 xlwings 라이브러리를 이용하고 있기 때문에 엑셀 작업이 훨씬 간단하지만 -
1
2
|
COT['Netlong_change'] = COT['Netlong'] - COT['Netlong'].shift(1)
|
cs |
위와 같이 계산하게 되면 결과값이 이상하다.
왜?
데이터가 행으로 일자로 정리되어 있기 때문에 위와 같은 코드는 단순히 한 행이 모두 이동해
품목이 섞이기 때문이다.
그래서, 품목별로 나눈 후에 계산을 해야한다.
여기서 활용되는 것이 isin 함수
1
2
|
COT[COT["Market_and_Exchange_Names"].isin(["WHEAT-SRW - CHICAGO BOARD OF TRADE"])]
|
cs |
위와 같이 품목별로 나누어 준다.
그런데
1
|
COT[COT['Market_and_Exchange_Names'].isin(['WHEAT-SRW - CHICAGO BOARD OF TRADE'])]['netlong_change'] = COT[COT['Market_and_Exchange_Names'].isin(['WHEAT-SRW - CHICAGO BOARD OF TRADE'])]['Netlong'] - COT[COT['Market_and_Exchange_Names'].isin(['WHEAT-SRW - CHICAGO BOARD OF TRADE'])]['Netlong'].shift(1)
|
cs |
위와 같이 작성하면 settingwithcopywarning 오류가 나면서 계산이 안된다.
이유는 1번 stackoverflow를 읽어보면 자세하게 설명이 되어 있다.
4. 해결책
1
2
3
4
5
|
df = COT[COT['Market_and_Exchange_Names'].isin(['WHEAT-SRW - CHICAGO BOARD OF TRADE'])]['Netlong']- COT[COT['Market_and_Exchange_Names'].isin(['WHEAT-SRW - CHICAGO BOARD OF TRADE'])]['Netlong'].shift(1)
df1 = pd.DataFrame(df)
df1.columns = ['Netlong_change']
df2 = pd.merge(COT[COT['Market_and_Exchange_Names'].isin(['WHEAT-SRW - CHICAGO BOARD OF TRADE'])], df1, left_index= True, right_index = True)
df2
|
cs |
다른 방법이 있는지는 잘 모르겠지만 여튼 위와 같은 형태로.