日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

那些功能逆天,却鲜为人知的pandas骚操作

發(fā)布時(shí)間:2024/9/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 那些功能逆天,却鲜为人知的pandas骚操作 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


文章來(lái)源:Python數(shù)據(jù)科學(xué)

作者:東哥

pandas有些功能很逆天,但卻鮮為人知,本篇給大家盤(pán)點(diǎn)一下。

一、ACCESSOR

pandas有一種功能非常強(qiáng)大的方法,它就是accessor,可以將它理解為一種屬性接口,通過(guò)它可以獲得額外的方法。其實(shí)這樣說(shuō)還是很籠統(tǒng),下面我們通過(guò)代碼和實(shí)例來(lái)理解一下。

>>>?pd.Series._accessors {'cat',?'str',?'dt'}

對(duì)于Series數(shù)據(jù)結(jié)構(gòu)使用_accessors方法,可以得到了3個(gè)對(duì)象:cat,str,dt。

  • .cat:用于分類數(shù)據(jù)(Categorical data)

  • .str:用于字符數(shù)據(jù)(String Object data)

  • .dt:用于時(shí)間數(shù)據(jù)(datetime-like data)

下面我們依次看一下這三個(gè)對(duì)象是如何使用的。

str對(duì)象的使用

Series數(shù)據(jù)類型:str字符串

#?定義一個(gè)Series序列 >>>?addr?=?pd.Series([ ...?????'Washington,?D.C.?20003', ...?????'Brooklyn,?NY?11211-1755', ...?????'Omaha,?NE?68154', ...?????'Pittsburgh,?PA?15211' ...?])?>>>?addr.str.upper() 0?????WASHINGTON,?D.C.?20003 1????BROOKLYN,?NY?11211-1755 2????????????OMAHA,?NE?68154 3???????PITTSBURGH,?PA?15211 dtype:?object>>>?addr.str.count(r'\d')? 0????5 1????9 2????5 3????5 dtype:?int64

關(guān)于以上str對(duì)象的2個(gè)方法說(shuō)明:

  • Series.str.upper:將Series中所有字符串變?yōu)榇髮?xiě)

  • Series.str.count:對(duì)Series中所有字符串的個(gè)數(shù)進(jìn)行計(jì)數(shù)

其實(shí)不難發(fā)現(xiàn),該用法的使用與Python中字符串的操作很相似。沒(méi)錯(cuò),在pandas中你一樣可以這樣簡(jiǎn)單的操作,而不同的是你操作的是一整列的字符串?dāng)?shù)據(jù)。仍然基于以上數(shù)據(jù)集,再看它的另一個(gè)操作:

>>>?regex?=?(r'(?P<city>[A-Za-z?]+),?'??????#?一個(gè)或更多字母 ...??????????r'(?P<state>[A-Z]{2})?'????????#?兩個(gè)大寫(xiě)字母 ...??????????r'(?P<zip>\d{5}(?:-\d{4})?)')??#?可選的4個(gè)延伸數(shù)字 ... >>>?addr.str.replace('.',?'').str.extract(regex)city?state?????????zip 0??Washington????DC???????20003 1????Brooklyn????NY??11211-1755 2???????Omaha????NE???????68154 3??Pittsburgh????PA???????15211

關(guān)于以上str對(duì)象的2個(gè)方法說(shuō)明:

  • Series.str.replace:將Series中指定字符串替換

  • Series.str.extract:通過(guò)正則表達(dá)式提取字符串中的數(shù)據(jù)信息

這個(gè)用法就有點(diǎn)復(fù)雜了,因?yàn)楹苊黠@看到,這是一個(gè)鏈?zhǔn)降挠梅āMㄟ^(guò)replace將?" . " 替換為"",即為空緊接著又使用了3個(gè)正則表達(dá)式(分別對(duì)應(yīng)city,state,zip)通過(guò)extract對(duì)數(shù)據(jù)進(jìn)行了提取并由原來(lái)的Series數(shù)據(jù)結(jié)構(gòu)變?yōu)榱薉ataFrame數(shù)據(jù)結(jié)構(gòu)。

當(dāng)然,除了以上用法外,常用的屬性和方法還有.rstrip,.contains,split等,我們通過(guò)下面代碼查看一下str屬性的完整列表:

>>>?[i?for?i?in?dir(pd.Series.str)?if?not?i.startswith('_')] ['capitalize','cat','center','contains','count','decode','encode','endswith','extract','extractall','find','findall','get','get_dummies','index','isalnum','isalpha','isdecimal','isdigit','islower','isnumeric','isspace','istitle','isupper','join','len','ljust','lower','lstrip','match','normalize','pad','partition','repeat','replace','rfind','rindex','rjust','rpartition','rsplit','rstrip','slice','slice_replace','split','startswith','strip','swapcase','title','translate','upper','wrap','zfill']

屬性有很多,對(duì)于具體的用法,如果感興趣可以自己進(jìn)行摸索練習(xí)。

dt對(duì)象的使用

Series數(shù)據(jù)類型:datetime

因?yàn)閿?shù)據(jù)需要datetime類型,所以下面使用pandas的date_range()生成了一組日期datetime演示如何進(jìn)行dt對(duì)象操作。

>>>?daterng?=?pd.Series(pd.date_range('2017',?periods=9,?freq='Q')) >>>?daterng 0???2017-03-31 1???2017-06-30 2???2017-09-30 3???2017-12-31 4???2018-03-31 5???2018-06-30 6???2018-09-30 7???2018-12-31 8???2019-03-31 dtype:?datetime64[ns]>>>??daterng.dt.day_name() 0??????Friday 1??????Friday 2????Saturday 3??????Sunday 4????Saturday 5????Saturday 6??????Sunday 7??????Monday 8??????Sunday dtype:?object>>>?#?查看下半年 >>>?daterng[daterng.dt.quarter?>?2] 2???2017-09-30 3???2017-12-31 6???2018-09-30 7???2018-12-31 dtype:?datetime64[ns]>>>?daterng[daterng.dt.is_year_end] 3???2017-12-31 7???2018-12-31 dtype:?datetime64[ns]

以上關(guān)于dt的3種方法說(shuō)明:

  • Series.dt.day_name():從日期判斷出所處星期數(shù)

  • Series.dt.quarter:從日期判斷所處季節(jié)

  • Series.dt.is_year_end:從日期判斷是否處在年底

其它方法也都是基于datetime的一些變換,并通過(guò)變換來(lái)查看具體微觀或者宏觀日期。

cat對(duì)象的使用

Series數(shù)據(jù)類型:Category

在說(shuō)cat對(duì)象的使用前,先說(shuō)一下Category這個(gè)數(shù)據(jù)類型,它的作用很強(qiáng)大。雖然我們沒(méi)有經(jīng)常性的在內(nèi)存中運(yùn)行上g的數(shù)據(jù),但是我們也總會(huì)遇到執(zhí)行幾行代碼會(huì)等待很久的情況。使用Category數(shù)據(jù)的一個(gè)好處就是:可以很好的節(jié)省在時(shí)間和空間的消耗。下面我們通過(guò)幾個(gè)實(shí)例來(lái)學(xué)習(xí)一下。

>>>?colors?=?pd.Series([ ...?????'periwinkle', ...?????'mint?green', ...?????'burnt?orange', ...?????'periwinkle', ...?????'burnt?orange', ...?????'rose', ...?????'rose', ...?????'mint?green', ...?????'rose', ...?????'navy' ...?]) ... >>>?import?sys >>>?colors.apply(sys.getsizeof) 0????59 1????59 2????61 3????59 4????61 5????53 6????53 7????59 8????53 9????53 dtype:?int64

上面我們通過(guò)使用sys.getsizeof來(lái)顯示內(nèi)存占用的情況,數(shù)字代表字節(jié)數(shù)。還有另一種計(jì)算內(nèi)容占用的方法:memory_usage(),后面會(huì)使用。

現(xiàn)在我們將上面colors的不重復(fù)值映射為一組整數(shù),然后再看一下占用的內(nèi)存。

>>>?mapper?=?{v:?k?for?k,?v?in?enumerate(colors.unique())} >>>?mapper {'periwinkle':?0,?'mint?green':?1,?'burnt?orange':?2,?'rose':?3,?'navy':?4}>>>?as_int?=?colors.map(mapper) >>>?as_int 0????0 1????1 2????2 3????0 4????2 5????3 6????3 7????1 8????3 9????4 dtype:?int64>>>?as_int.apply(sys.getsizeof) 0????24 1????28 2????28 3????24 4????28 5????28 6????28 7????28 8????28 9????28 dtype:?int64

注:對(duì)于以上的整數(shù)值映射也可以使用更簡(jiǎn)單的pd.factorize()方法代替。

我們發(fā)現(xiàn)上面所占用的內(nèi)存是使用object類型時(shí)的一半。其實(shí),這種情況就類似于Category data類型內(nèi)部的原理。

內(nèi)存占用區(qū)別:Categorical所占用的內(nèi)存與Categorical分類的數(shù)量和數(shù)據(jù)的長(zhǎng)度成正比,相反,object所占用的內(nèi)存則是一個(gè)常數(shù)乘以數(shù)據(jù)的長(zhǎng)度。

下面是object內(nèi)存使用和category內(nèi)存使用的情況對(duì)比。

>>>?colors.memory_usage(index=False,?deep=True) 650 >>>?colors.astype('category').memory_usage(index=False,?deep=True) 495

上面結(jié)果是使用object和Category兩種情況下內(nèi)存的占用情況。我們發(fā)現(xiàn)效果并沒(méi)有我們想象中的那么好。但是注意Category內(nèi)存是成比例的,如果數(shù)據(jù)集的數(shù)據(jù)量很大,但不重復(fù)分類(unique)值很少的情況下,那么Category的內(nèi)存占用可以節(jié)省達(dá)到10倍以上,比如下面數(shù)據(jù)量增大的情況:

>>>?manycolors?=?colors.repeat(10) >>>?len(manycolors)?/?manycolors.nunique()? 20.0>>>?manycolors.memory_usage(index=False,?deep=True) 6500 >>>?manycolors.astype('category').memory_usage(index=False,?deep=True) 585

可以看到,在數(shù)據(jù)量增加10倍以后,使用Category所占內(nèi)容節(jié)省了10倍以上。

除了占用內(nèi)存節(jié)省外,另一個(gè)額外的好處是計(jì)算效率有了很大的提升。因?yàn)閷?duì)于Category類型的Series,str字符的操作發(fā)生在.cat.categories的非重復(fù)值上,而并非原Series上的所有元素上。也就是說(shuō)對(duì)于每個(gè)非重復(fù)值都只做一次操作,然后再向與非重復(fù)值同類的值映射過(guò)去。

對(duì)于Category的數(shù)據(jù)類型,可以使用accessor的cat對(duì)象,以及相應(yīng)的屬性和方法來(lái)操作Category數(shù)據(jù)。

>>>?ccolors?=?colors.astype('category') >>>?ccolors.cat.categories Index(['burnt?orange',?'mint?green',?'navy',?'periwinkle',?'rose'],?dtype='object')

實(shí)際上,對(duì)于開(kāi)始的整數(shù)類型映射,可以先通過(guò)reorder_categories進(jìn)行重新排序,然后再使用cat.codes來(lái)實(shí)現(xiàn)對(duì)整數(shù)的映射,來(lái)達(dá)到同樣的效果。

>>>?ccolors.cat.reorder_categories(mapper).cat.codes 0????0 1????1 2????2 3????0 4????2 5????3 6????3 7????1 8????3 9????4 dtype:?int8

dtype類型是Numpy的int8(-127~128)。可以看出以上只需要一個(gè)單字節(jié)就可以在內(nèi)存中包含所有的值。我們開(kāi)始的做法默認(rèn)使用了int64類型,然而通過(guò)pandas的使用可以很智能的將Category數(shù)據(jù)類型變?yōu)樽钚〉念愋汀?/p>

讓我們來(lái)看一下cat還有什么其它的屬性和方法可以使用。下面cat的這些屬性基本都是關(guān)于查看和操作Category數(shù)據(jù)類型的。

>>>?[i?for?i?in?dir(ccolors.cat)?if?not?i.startswith('_')] ['add_categories','as_ordered','as_unordered','categories','codes','ordered','remove_categories','remove_unused_categories','rename_categories','reorder_categories','set_categories']

但是Category數(shù)據(jù)的使用不是很靈活。例如,插入一個(gè)之前沒(méi)有的值,首先需要將這個(gè)值添加到.categories的容器中,然后再添加值。

>>>?ccolors.iloc[5]?=?'a?new?color' #?... ValueError:?Cannot?setitem?on?a?Categorical?with?a?new?category, set?the?categories?first>>>?ccolors?=?ccolors.cat.add_categories(['a?new?color']) >>>?ccolors.iloc[5]?=?'a?new?color'??

如果你想設(shè)置值或重塑數(shù)據(jù),而非進(jìn)行新的運(yùn)算操作,那么Category類型不是那么有用。

二、從clipboard剪切板載入數(shù)據(jù)

當(dāng)我們的數(shù)據(jù)存在excel表里,或者其它的IDE編輯器中的時(shí)候,我們想要通過(guò)pandas載入數(shù)據(jù)。我們通常的做法是先保存再載入,其實(shí)這樣做起來(lái)十分繁瑣。一個(gè)簡(jiǎn)單的方法就是使用pd.read_clipboard()?直接從電腦的剪切板緩存區(qū)中提取數(shù)據(jù)。

這樣我們就可以直接將結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)變?yōu)镈ataFrame或者Series了。excel表中數(shù)據(jù)是這樣的:

在純文本文件中,比如txt文件,是這樣的:

a???b???????????c???????d 0???1???????????inf?????1/1/00 2???7.389056099?N/A?????5-Jan-13 4???54.59815003?nan?????7/24/18 6???403.4287935?None????NaT

將上面excel或者txt中的數(shù)據(jù)選中然后復(fù)制,然后使用pandas的read_clipboard()即可完成到DataFrame的轉(zhuǎn)換。parse_dates參數(shù)設(shè)置為 "d",可以自動(dòng)識(shí)別日期,并調(diào)整為xxxx-xx-xx的格式。

>>>?df?=?pd.read_clipboard(na_values=[None],?parse_dates=['d']) >>>?dfa?????????b????c??????????d 0??0????1.0000??inf?2000-01-01 1??2????7.3891??NaN?2013-01-05 2??4???54.5982??NaN?2018-07-24 3??6??403.4288??NaN????????NaT>>>?df.dtypes a?????????????int64 b???????????float64 c???????????float64 d????datetime64[ns] dtype:?object

三、將pandas對(duì)象轉(zhuǎn)換為“壓縮”格式

在pandas中,我們可以直接將objects打包成為 gzip, bz2, zip, or xz 等壓縮格式,而不必將沒(méi)壓縮的文件放在內(nèi)存中然后進(jìn)行轉(zhuǎn)化。來(lái)看一個(gè)例子如何使用:

>>>?abalone?=?pd.read_csv(url,?usecols=[0,?1,?2,?3,?4,?8],?names=cols)>>>?abalonesex??length???diam??height??weight??rings 0??????M???0.455??0.365???0.095??0.5140?????15 1??????M???0.350??0.265???0.090??0.2255??????7 2??????F???0.530??0.420???0.135??0.6770??????9 3??????M???0.440??0.365???0.125??0.5160?????10 4??????I???0.330??0.255???0.080??0.2050??????7 5??????I???0.425??0.300???0.095??0.3515??????8 6??????F???0.530??0.415???0.150??0.7775?????20 ...???..?????...????...?????...?????...????... 4170???M???0.550??0.430???0.130??0.8395?????10 4171???M???0.560??0.430???0.155??0.8675??????8 4172???F???0.565??0.450???0.165??0.8870?????11 4173???M???0.590??0.440???0.135??0.9660?????10 4174???M???0.600??0.475???0.205??1.1760??????9 4175???F???0.625??0.485???0.150??1.0945?????10 4176???M???0.710??0.555???0.195??1.9485?????12

導(dǎo)入文件,讀取并存為abalone(DataFrame結(jié)構(gòu))。當(dāng)我們要存為壓縮的時(shí)候,簡(jiǎn)單的使用?to_json()?即可輕松完成轉(zhuǎn)化過(guò)程。下面通過(guò)設(shè)置相應(yīng)參數(shù)將abalone存為了.gz格式的壓縮文件。

abalone.to_json('df.json.gz',?orient='records',lines=True,?compression='gzip')

如果我們想知道儲(chǔ)存壓縮文件的大小,可以通過(guò)內(nèi)置模塊os.path,使用getsize方法來(lái)查看文件的字節(jié)數(shù)。下面是兩種格式儲(chǔ)存文件的大小對(duì)比。

>>>?import?os.path >>>?abalone.to_json('df.json',?orient='records',?lines=True) >>>?os.path.getsize('df.json')?/?os.path.getsize('df.json.gz') 11.603035760226396

四、使用"測(cè)試模塊"制作偽數(shù)據(jù)

在pandas中,有一個(gè)測(cè)試模塊可以幫助我們生成半真實(shí)(偽數(shù)據(jù)),并進(jìn)行測(cè)試,它就是util.testing。下面同我們通過(guò)一個(gè)簡(jiǎn)單的例子看一下如何生成數(shù)據(jù)測(cè)試:

>>>?import?pandas.util.testing?as?tm >>>?tm.N,?tm.K?=?15,?3??#?默認(rèn)的行和列>>>?import?numpy?as?np >>>?np.random.seed(444)>>>?tm.makeTimeDataFrame(freq='M').head()A???????B???????C 2000-01-31??0.3574?-0.8804??0.2669 2000-02-29??0.3775??0.1526?-0.4803 2000-03-31??1.3823??0.2503??0.3008 2000-04-30??1.1755??0.0785?-0.1791 2000-05-31?-0.9393?-0.9039??1.1837>>>?tm.makeDataFrame().head()A???????B???????C nTLGGTiRHF?-0.6228??0.6459??0.1251 WPBRn9jtsR?-0.3187?-0.8091??1.1501 7B3wWfvuDA?-1.9872?-1.0795??0.2987 yJ0BTjehH1??0.8802??0.7403?-1.2154 0luaYUYvy1?-0.9320??1.2912?-0.2907

上面簡(jiǎn)單的使用了

makeTimeDataFrame?和?makeDataFrame?分別生成了一組時(shí)間數(shù)據(jù)和DataFrame的數(shù)據(jù)。但這只是其中的兩個(gè)用法,關(guān)于testing中的方法有大概30多個(gè),如果你想全部了解,可以通過(guò)查看dir獲得:

>>>?[i?for?i?in?dir(tm)?if?i.startswith('make')] ['makeBoolIndex','makeCategoricalIndex','makeCustomDataframe','makeCustomIndex',#?...,'makeTimeSeries','makeTimedeltaIndex','makeUIntIndex','makeUnicodeIndex']

五、從列項(xiàng)中創(chuàng)建DatetimeIndex

也許我們有的時(shí)候會(huì)遇到這樣的情形(為了說(shuō)明這種情情況,我使用了product進(jìn)行交叉迭代的創(chuàng)建了一組關(guān)于時(shí)間的數(shù)據(jù)):

>>>?from?itertools?import?product >>>?datecols?=?['year',?'month',?'day']>>>?df?=?pd.DataFrame(list(product([2017,?2016],?[1,?2],?[1,?2,?3])), ...???????????????????columns=datecols) >>>?df['data']?=?np.random.randn(len(df)) >>>?dfyear??month??day????data 0???2017??????1????1?-0.0767 1???2017??????1????2?-1.2798 2???2017??????1????3??0.4032 3???2017??????2????1??1.2377 4???2017??????2????2?-0.2060 5???2017??????2????3??0.6187 6???2016??????1????1??2.3786 7???2016??????1????2?-0.4730 8???2016??????1????3?-2.1505 9???2016??????2????1?-0.6340 10??2016??????2????2??0.7964 11??2016??????2????3??0.0005

明顯看到,列項(xiàng)中有year,month,day,它們分別在各個(gè)列中,而并非是一個(gè)完整日期。那么如何從這些列中將它們組合在一起并設(shè)置為新的index呢?

通過(guò)to_datetime的使用,我們就可以直接將年月日組合為一個(gè)完整的日期,然后賦給索引。代碼如下:

>>>?df.index?=?pd.to_datetime(df[datecols]) >>>?df.head()year??month??day????data 2017-01-01??2017??????1????1?-0.0767 2017-01-02??2017??????1????2?-1.2798 2017-01-03??2017??????1????3??0.4032 2017-02-01??2017??????2????1??1.2377 2017-02-02??2017??????2????2?-0.2060

當(dāng)然,你可以選擇將原有的年月日列移除,只保留data數(shù)據(jù)列,然后squeeze轉(zhuǎn)換為Series結(jié)構(gòu)。

>>>?df?=?df.drop(datecols,?axis=1).squeeze() >>>?df.head() 2017-01-01???-0.0767 2017-01-02???-1.2798 2017-01-03????0.4032 2017-02-01????1.2377 2017-02-02???-0.2060 Name:?data,?dtype:?float64>>>?df.index.dtype_str 'datetime64[ns]The End來(lái)和小伙伴們一起向上生長(zhǎng)呀!掃描下方二維碼,添加小詹微信,可領(lǐng)取千元大禮包并申請(qǐng)加入 Python 學(xué)習(xí)交流群,群內(nèi)僅供學(xué)術(shù)交流,日常互動(dòng),如果是想發(fā)推文、廣告、砍價(jià)小程序的敬請(qǐng)繞道!一定記得備注「交流學(xué)習(xí)」,我會(huì)盡快通過(guò)好友申請(qǐng)哦!????長(zhǎng)按識(shí)別,添加微信(添加人數(shù)較多,請(qǐng)耐心等待)????長(zhǎng)按識(shí)別,關(guān)注小詹(掃碼回復(fù) 1024 領(lǐng)取程序員大禮包)

總結(jié)

以上是生活随笔為你收集整理的那些功能逆天,却鲜为人知的pandas骚操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。