Päivitin juuri Pandasin 0.11:stä 0.13.0rc1:een. Nyt sovellus antaa monia uusia varoituksia. Yksi niistä on tällainen:
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
Haluan tietää, mitä se tarkalleen ottaen tarkoittaa? Pitääkö minun muuttaa jotain?
Miten minun pitäisi keskeyttää varoitus, jos vaadin käyttää quote_df['TVol'] = quote_df['TVol']/TVOL_SCALE
?
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
luotiin merkitsemään mahdollisesti hämmentäviä "ketjutettuja" määrityksiä, kuten seuraavat, jotka eivät aina toimi odotetusti, erityisesti kun ensimmäinen valinta palauttaa kopion. [Katso GH5390 ja GH5597 taustakeskustelua varten.]]
df[df['A'] > 2]['B'] = new_val # new_val not set in df
Varoitus tarjoaa ehdotuksen kirjoittaa uudelleen seuraavasti:
df.loc[df['A'] > 2, 'B'] = new_val
Tämä ei kuitenkaan sovi käyttöösi, joka vastaa seuraavaa:
df = df[df['A'] > 2]
df['B'] = new_val
Vaikka on selvää, että et välitä siitä, että kirjoitukset pääsevät takaisin alkuperäiseen kehykseen (koska ylikirjoitit viittauksen siihen), valitettavasti tätä mallia ei voida erottaa ensimmäisestä ketjutetusta osoitusesimerkistä, mistä johtuu (väärä positiivinen) varoitus. Väärien positiivisten tulosten mahdollisuutta käsitellään docs on indexing, jos haluat lukea lisää. Voit turvallisesti poistaa tämän uuden varoituksen käytöstä seuraavalla osoituksella.
pd.options.mode.chained_assignment = None # default='warn'
Yleisesti ottaen SettingWithCopyWarning
-varoituksen tarkoitus on osoittaa käyttäjille (ja erityisesti uusille käyttäjille), että he voivat käyttää kopiota eivätkä alkuperäistä, kuten he luulevat. Vääriä positiivisia tuloksia on (eli jos tiedät mitä teet, se voi olla ok). Yksi mahdollisuus on yksinkertaisesti kytkeä (oletusarvoisesti varoitus) varoitus pois päältä, kuten @Garrett ehdottaa.
Tässä on toinen vaihtoehto:
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
Voit asettaa is_copy
-lipun arvoon False
, jolloin tarkistus kytkeytyy pois päältä tämän objektin osalta:
In [5]: dfa.is_copy = False
In [6]: dfa['A'] /= 2
Jos kopioit nimenomaisesti, mitään muuta varoitusta ei tapahdu:
In [7]: dfa = df.ix[:, [1, 0]].copy()
In [8]: dfa['A'] /= 2
Vaikka OP:n edellä esittämä koodi on laillinen ja luultavasti jotain, mitä minäkin teen, se on teknisesti ottaen tämän varoituksen tapaus eikä väärä positiivinen tulos. Toinen tapa ei saada varoitusta olisi tehdä valintaoperaatio reindex
:n kautta, esim.
quote_df = quote_df.reindex(columns=['STK', ...])
Tai,
quote_df = quote_df.reindex(['STK', ...], axis=1) # v.0.21
Kun teet jotain tällaista:
quote_df = quote_df.ix[:,[0,3,2,1,4,5,8,9,30,31]]
pandas.ix
tässä tapauksessa palauttaa uuden, itsenäisen datakehyksen.
Kaikki arvot, joita päätät muuttaa tässä tietoruudussa, eivät muuta alkuperäistä tietoruutua.
Tästä pandas yrittää varoittaa sinua.
.ix
on huono idea.ix
-olio yrittää tehdä useampaa kuin yhtä asiaa, ja kaikille, jotka ovat lukeneet jotain puhtaasta koodista, tämä on vahva haju.
Annetaan tämä tietoruutu:
df = pd.DataFrame({"a": [1,2,3,4], "b": [1,1,2,2]})
Kaksi käyttäytymistä:
dfcopy = df.ix[:,["a"]]
dfcopy.a.ix[0] = 2
Käyttäytyminen yksi: dfcopy
on nyt itsenäinen datakehys. Sen muuttaminen ei muuta df
df.ix[0, "a"] = 3
Käyttäytyminen kaksi: Tämä muuttaa alkuperäistä datakehystä.
.loc
sen sijaanPandakehittäjät huomasivat, että .ix
-objekti oli melko haiseva[spekulatiivisesti] ja loivat siksi kaksi uutta objektia, jotka auttavat tietojen liittämisessä ja osoittamisessa. (Toinen on .iloc
)
.loc
on nopeampi, koska se ei yritä luoda kopiota datasta.
.loc
on tarkoitettu muuttamaan olemassa olevaa datakehystäsi inplace, mikä on muistitehokkaampaa.
.loc
on ennustettavissa, sillä on yksi käyttäytyminen.
Koodiesimerkissäsi lataat ison tiedoston, jossa on paljon sarakkeita, ja muokkaat sen sitten pienemmäksi.
pd.read_csv
-funktio voi auttaa sinua paljon tässä ja myös nopeuttaa tiedoston lataamista huomattavasti.
Sen sijaan, että tekisit näin
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]]
Tee näin
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
Tämä lukee vain ne sarakkeet, joista olet kiinnostunut, ja nimeää ne oikein. Ei tarvitse käyttää pahaa .ix
-objektia tekemään maagisia juttuja.