Pandas'ımı 0.11'den 0.13.0rc1'e yeni yükselttim. Şimdi, uygulama birçok yeni uyarı veriyor. Bunlardan biri şöyle:
E:\FinReporter\FM_EXT.py:449: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE
Tam olarak ne anlama geldiğini bilmek istiyorum? Bir şeyi değiştirmem gerekiyor mu?
Eğer quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE
kullanmakta ısrar edersem uyarıyı nasıl askıya almalıyım?
def _decode_stock_quote(list_of_150_stk_str):
"""decode the webpage and return dataframe"""
from cStringIO import StringIO
str_of_all = "".join(list_of_150_stk_str)
quote_df = pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}
quote_df.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)
quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]
quote_df['TClose'] = quote_df['TPrice']
quote_df['RT'] = 100 * (quote_df['TPrice']/quote_df['TPCLOSE'] - 1)
quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE
quote_df['TAmt'] = quote_df['TAmt']/TAMT_SCALE
quote_df['STK_ID'] = quote_df['STK'].str.slice(13,19)
quote_df['STK_Name'] = quote_df['STK'].str.slice(21,30)#.decode('gb2312')
quote_df['TDate'] = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])
return quote_df
E:\FinReporter\FM_EXT.py:449: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE
E:\FinReporter\FM_EXT.py:450: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
quote_df['TAmt'] = quote_df['TAmt']/TAMT_SCALE
E:\FinReporter\FM_EXT.py:453: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
quote_df['TDate'] = quote_df.TDate.map(lambda x: x[0:4]+x[5:7]+x[8:10])
SettingWithCopyWarning`, özellikle ilk seçim bir kopya döndürdüğünde, her zaman beklendiği gibi çalışmayan aşağıdaki gibi potansiyel olarak kafa karıştırıcı "chained" atamaları işaretlemek için oluşturulmuştur. [arka plan tartışması için GH5390 ve GH5597'ye bakın].
df[df['A'] > 2]['B'] = new_val # new_val not set in df
Uyarı, aşağıdaki şekilde yeniden yazılması için bir öneri sunmaktadır:
df.loc[df['A'] > 2, 'B'] = new_val
Ancak, bu sizin kullanımınıza uymuyor, bu da şu anlama geliyor:
df = df[df['A'] > 2]
df['B'] = new_val
Orijinal çerçeveye geri dönen yazıları önemsemediğiniz açık olsa da (referansın üzerine yazdığınız için), ne yazık ki bu model ilk zincirleme atama örneğinden ayırt edilemez, dolayısıyla (yanlış pozitif) uyarı. Eğer daha fazla okumak isterseniz, yanlış pozitifler için potansiyel indeksleme dokümanları'de ele alınmıştır. Bu yeni uyarıyı aşağıdaki atama ile güvenli bir şekilde devre dışı bırakabilirsiniz.
pd.options.mode.chained_assignment = None # default='warn'
Genel olarak SettingWithCopyWarning
uyarısının amacı, kullanıcılara (ve özellikle yeni kullanıcılara) düşündükleri gibi orijinal değil, bir kopya üzerinde çalışıyor olabileceklerini göstermektir. Yanlış pozitifler vardır (yani ne yaptığınızı biliyorsanız tamam olabilir). Bir olasılık, @Garrett'in önerdiği gibi (varsayılan olarak uyarı) uyarısını kapatmaktır.
İşte başka bir seçenek:
In [1]: df = DataFrame(np.random.randn(5, 2), columns=list('AB'))
In [2]: dfa = df.ix[:, [1, 0]]
In [3]: dfa.is_copy
Out[3]: True
In [4]: dfa['A'] /= 2
/usr/local/bin/ipython:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
#!/usr/local/bin/python
is_copybayrağını
False` olarak ayarlayabilirsiniz, bu da o nesne için kontrolü etkin bir şekilde kapatacaktır:
In [5]: dfa.is_copy = False
In [6]: dfa['A'] /= 2
Açıkça kopyalarsanız, başka bir uyarı olmayacaktır:
In [7]: dfa = df.ix[:, [1, 0]].copy()
In [8]: dfa['A'] /= 2
OP'nin yukarıda gösterdiği kod meşru olsa da ve muhtemelen benim de yaptığım bir şey olsa da, teknik olarak bu uyarı için bir durumdur ve yanlış pozitif değildir. Uyarıyı almamak için başka bir yol da seçim işlemini reindex
üzerinden yapmaktır, örn.
quote_df = quote_df.reindex(columns=['STK', ...])
Ya da,
quote_df = quote_df.reindex(['STK', ...], axis=1) # v.0.21
Gidip böyle bir şey yaptığınızda:
quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]
"pandas.ix" bu durumda yeni, tek başına bir veri çerçevesi döndürür.
Bu veri çerçevesinde değiştirmeye karar verdiğiniz herhangi bir değer, orijinal veri çerçevesini değiştirmeyecektir.
Pandalar sizi bu konuda uyarmaya çalışır.
.ix
is a bad idea.ix` nesnesi birden fazla şey yapmaya çalışır ve temiz kod hakkında bir şeyler okuyan herkes için bu güçlü bir kokudur.
Bu veri çerçevesi göz önüne alındığında:
df = pd.DataFrame({"a": [1,2,3,4], "b": [1,1,2,2]})
İki davranış:
dfcopy = df.ix[:,["a"]]
dfcopy.a.ix[0] = 2
Birinci davranış: dfcopy
artık tek başına bir veri çerçevesidir. Bunu değiştirmek df
'yi değiştirmeyecektir
df.ix[0, "a"] = 3
İkinci davranış: Bu, orijinal veri çerçevesini değiştirir.
.loc
kullanınPandas geliştiricileri .ix' nesnesinin oldukça kötü koktuğunu fark ettiler [spekülatif olarak] ve bu nedenle verilerin katılımına ve atanmasına yardımcı olan iki yeni nesne oluşturdular. (Diğeri
.iloc`)
.loc` daha hızlıdır, çünkü verilerin bir kopyasını oluşturmaya çalışmaz.
.loc` mevcut veri çerçevenizi yerinde değiştirmek içindir, bu da bellek açısından daha verimlidir.
.loc` tahmin edilebilirdir, tek bir davranışı vardır.
Kod örneğinizde yaptığınız şey, çok sayıda sütun içeren büyük bir dosyayı yüklemek ve daha sonra bunu daha küçük olacak şekilde değiştirmektir.
pd.read_csv` fonksiyonu bu konuda size çok yardımcı olabilir ve ayrıca dosyanın yüklenmesini çok daha hızlı hale getirebilir.
Yani bunu yapmak yerine
quote_df = pd.read_csv(StringIO(str_of_all), sep=',', names=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg')) #dtype={'A': object, 'B': object, 'C': np.float64}
quote_df.rename(columns={'A':'STK', 'B':'TOpen', 'C':'TPCLOSE', 'D':'TPrice', 'E':'THigh', 'F':'TLow', 'I':'TVol', 'J':'TAmt', 'e':'TDate', 'f':'TTime'}, inplace=True)
quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]
Bunu yap
columns = ['STK', 'TPrice', 'TPCLOSE', 'TOpen', 'THigh', 'TLow', 'TVol', 'TAmt', 'TDate', 'TTime']
df = pd.read_csv(StringIO(str_of_all), sep=',', usecols=[0,3,2,1,4,5,8,9,30,31])
df.columns = columns
Bu, yalnızca ilgilendiğiniz sütunları okuyacak ve bunları uygun şekilde adlandıracaktır. Sihirli şeyler yapmak için kötü .ix
nesnesini kullanmaya gerek yoktur.