熬夜整理,Pandas最常見的10個(gè)問題解答!
StactOverFlow論壇十問
問題1:
如何遍歷Pandas中Dataframe對(duì)象的行
https://stackoverflow.com/questions/16476924/how-to-iterate-over-rows-in-a-dataframe-in-pandas
如下是一個(gè)Pandas中的DataFrame對(duì)象
import?pandas?as?pd
inp?=?[{'c1':10,?'c2':100},?{'c1':11,'c2':110},?{'c1':12,'c2':120}]
df?=?pd.DataFrame(inp)
print?df
運(yùn)行代碼輸出:
???c1???c2
0??10??100
1??11??110
2??12??120
我想通過遍歷這個(gè)結(jié)果集的行,以及列名讀取每個(gè)單元格中的值,例如:
for?row?in?df.rows:
???print?row['c1'],?row['c2']
Pandas中有這樣的方法嗎?
我在論壇里發(fā)現(xiàn)了另外一個(gè)類似的問題,但是沒有我想要的答案。例如,他建議使用如下代碼:
for?date,?row?in?df.T.iteritems():
或者
for?row?in?df.iterrows():
但是我不太理解這個(gè)row對(duì)象,我該如何使用它?
最佳答案:
DataFrame.iterrows 是一個(gè)能夠同時(shí)生成行索引和行對(duì)象(以Series形式輸出)的生成器,例如:
import?pandas?as?pd
df?=?pd.DataFrame({'c1':?[10,?11,?12],?'c2':?[100,?110,?120]})
for?index,?row?in?df.iterrows():
????print(row['c1'],?row['c2'])
輸出:
10?100
11?110
12?120
問題2:
如何通過列值來選擇一個(gè)DataFrame對(duì)象的行?
https://stackoverflow.com/questions/17071871/how-do-i-select-rows-from-a-dataframe-based-on-column-values
我如何能夠通過Pandas中Dataframe對(duì)象的某列值來選擇對(duì)應(yīng)的行呢?
比如在SQL中,我們會(huì)這樣用:
SELECT?*
FROM?table
WHERE?column_name?=?some_value
看了下Pandas官方文檔,似乎沒有答案。
最佳答案
選擇屬于某個(gè)特定列值對(duì)應(yīng)的行,如some_value,可以使用==:
df.loc[df['column_name']?==?some_value]
選擇屬于某個(gè)列值序列對(duì)應(yīng)的行,如some_values,可以使用isin:
df.loc[df['column_name'].isin(some_values)]
結(jié)合多個(gè)條件的篩選可以使用 &:
df.loc[(df['column_name']?>=?A)?&?(df['column_name']?<=?B)]
注意這里的括號(hào)。由于Python中的運(yùn)算符優(yōu)先級(jí)規(guī)則,& 符作用域要比 <= 和 >=要窄, 因此,剛才代碼中的括號(hào)是必須要添加上的。
如果沒有括號(hào)就是如下情況:
df['column_name']?>=?A?&?df['column_name']?<=?B
就等同于:
df['column_name']?>=?(A?&?df['column_name'])?<=?B
這將產(chǎn)生Series對(duì)象的真值是模糊的錯(cuò)誤。(Truth value of a Series is ambiguous error.)
如果要選擇對(duì)應(yīng)列值不等于某個(gè)值對(duì)應(yīng)的行,可以使用!=:
df.loc[df['column_name']?!=?some_value]
isin會(huì)返回一個(gè)布爾型Series對(duì)象,因此要選擇不等于某些列值的行時(shí),可以將對(duì)應(yīng)的布爾型序列進(jìn)行取反:
df.loc[~df['column_name'].isin(some_values)]
例如:
import?pandas?as?pd
import?numpy?as?np
df?=?pd.DataFrame({'A':?'foo?bar?foo?bar?foo?bar?foo?foo'.split(),
???????????????????'B':?'one?one?two?three?two?two?one?three'.split(),
???????????????????'C':?np.arange(8),?'D':?np.arange(8)?*?2})
print(df)
#??????A??????B??C???D
#?0??foo????one??0???0
#?1??bar????one??1???2
#?2??foo????two??2???4
#?3??bar??three??3???6
#?4??foo????two??4???8
#?5??bar????two??5??10
#?6??foo????one??6??12
#?7??foo??three??7??14
print(df.loc[df['A']?==?'foo'])
輸出:
?????A??????B??C???D
0??foo????one??0???0
2??foo????two??2???4
4??foo????two??4???8
6??foo????one??6??12
7??foo??three??7??14
如果你有多個(gè)值想要包含進(jìn)去,那可以把他們放入一個(gè)列表中(或者任意的序列類結(jié)構(gòu)中)并且使用isin
print(df.loc[df['B'].isin(['one','three'])])
輸出:
?????A??????B??C???D
0??foo????one??0???0
1??bar????one??1???2
3??bar??three??3???6
6??foo????one??6??12
7??foo??three??7??14
不過注意,更有效地方式是將你要查找的列指定為列索引然后再去使用df.loc方法去定位指定的列值,會(huì)更有效率:
df?=?df.set_index(['B'])
print(df.loc['one'])
yields
???????A??C???D
B??????????????
one??foo??0???0
one??bar??1???2
one??foo??6??12
或者,通過df.index.isin篩選指定行索引中包含多個(gè)你的指定值,來篩選結(jié)果集: or, to include multiple values from the index use df.index.isin:
df.loc[df.index.isin(['one','two'])]
輸出:
???????A??C???D
B??????????????
one??foo??0???0
one??bar??1???2
two??foo??2???4
two??foo??4???8
two??bar??5??10
one??foo??6??12
問題3
重命名Pandas中的列名
https://stackoverflow.com/questions/11346283/renaming-column-names-in-pandas
我有一個(gè)DataFrame對(duì)象需要對(duì)它原始的列標(biāo)簽進(jìn)行替換,我想對(duì)這個(gè)DataFrame對(duì)象A做如下操作,它起始的列名如下:
['$a',?'$b',?'$c',?'$d',?'$e']
需要轉(zhuǎn)化為:
['a',?'b',?'c',?'d',?'e']
我已經(jīng)將編輯好的列名儲(chǔ)存到了一個(gè)列表中,但是不知道如何能夠替換DataFrame的列名
最佳答案
只需要對(duì)列屬性.columns進(jìn)行指定即可
>>>?df?=?pd.DataFrame({'$a':[1,2],?'$b':?[10,20]})
>>>?df
???$a??$b
0???1??10
1???2??20
>>>?df.columns?=?['a',?'b']
>>>?df
???a???b
0??1??10
1??2??20
問題4:
如何刪除DataFrame對(duì)象中的列
https://stackoverflow.com/questions/13411544/delete-a-column-from-a-pandas-dataframe
當(dāng)我們刪除DataFrame中的一列時(shí)我會(huì)使用:
del?df['column_name']
這個(gè)沒有問題,但是為什么這種用法就不行呢?
del?df.column_name
既然能夠通過df.column_name訪問列或者Series對(duì)象,我覺得應(yīng)該可以得到同樣的效果。
最佳答案:
正如你提到的,正確的寫法是:
del?df['column_name']
由于Python的同步限制,很難通過del df.column_name來達(dá)到刪除的作用,因?yàn)樵赑ython的底層 del df[name] 等價(jià)于df.delitem(name)
問題5:
如何選擇DataFrame中的多列:
https://stackoverflow.com/questions/11285613/selecting-multiple-columns-in-a-pandas-dataframe
我有一個(gè)不同列組成的數(shù)據(jù),但是我不知道如何提取某些列數(shù)據(jù)并將他們保存到另外一個(gè)變量中去,
比如:
index??a???b???c
1??????2???3???4
2??????3???4???5
我該如何把選中的‘a(chǎn)’,‘b’列保存另外一個(gè)變量df1中呢?
我的方法是:
df1?=?df['a':'b']
df1?=?df.ix[:,?'a':'b']
但上面的方法都不能解決問題。
最佳答案
列名由于是字符串,它不能通過你使用的切片方式進(jìn)行提取。
你其實(shí)有多種選擇,如果你知道哪些變量是想要提取出來的,你可以傳入一個(gè)包含這些列的列表到底層的_getitem_方法中,也就是[]花式索引,例如:
df1?=?df[['a',?'b']]
此外,如果是通過數(shù)字來索引,而不是通過它們的名字(例如你的代碼可以忽略列名而是直接提取前兩列)那你可以使用下面的方法:
df1?=?df.iloc[:,?0:2]?#?注意Python的切片是不能夠提取結(jié)尾的索引編號(hào)對(duì)應(yīng)的值的
此外,你還要熟悉一個(gè)思維方式,訪問Pandas對(duì)象和復(fù)制這個(gè)對(duì)象的區(qū)別,剛才我提供的第一種方法是在內(nèi)容中返回了一個(gè)想要的對(duì)象的復(fù)制品。
當(dāng)然有時(shí),Pandas中的索引規(guī)范并非全都遵循這樣的規(guī)則,而是會(huì)給你一個(gè)全新的變量,他會(huì)引用相同的內(nèi)存空間作為一個(gè)次級(jí)的對(duì)象,或者源對(duì)象的一個(gè)片段。這種方式一般是我給你展示的第二種方法中的原理,因此你可以通過.copy()修改它,獲取到一個(gè)正常的復(fù)制品。不過這種情況下,改變你認(rèn)為的切片對(duì)象有時(shí)會(huì)改變?cè)械膶?duì)象,因此要格外小心這種情況的發(fā)生。
df1?=?df.iloc[0,?0:2].copy()?#?為了避免同時(shí)改變df1和df2,你可以這樣操作
使用iloc方法時(shí),你需要找到列的位置,你可以通過使用get_loc方法準(zhǔn)確獲取列的索引,
{df.columns.get_loc(c):?c?for?idx,?c?in?enumerate(df.columns)}
現(xiàn)在使用這個(gè)字典來獲取列名和iloc方法是不是更方便了呢?
問題6:
https://stackoverflow.com/questions/15943769/how-do-i-get-the-row-count-of-a-pandas-dataframe
如何數(shù)Pandas中DataFrame對(duì)象的行數(shù)?
我嘗試通過以下兩種Pandas中DataFrame的方法來獲取行數(shù),但是均告失敗,請(qǐng)問我錯(cuò)在哪里,請(qǐng)看代碼.
方法1:
total_rows?=?df.count
print?total_rows?+?1
方法2:
total_rows?=?df['First_column_label'].count
print?total_rows?+?1
報(bào)錯(cuò)信息均是:
TypeError:?unsupported?operand?type(s)?for?+:?'instancemethod'?and?'int'
最佳回答
對(duì)于DataFrame對(duì)象,你可以用下面的任何一種方法來實(shí)現(xiàn)對(duì)行數(shù)的計(jì)數(shù):
len(df.index)
df.shape[0]
df[df.columns[0]].count()?#?等價(jià)于統(tǒng)計(jì)第一列中的非空元素的行數(shù)
也可以通過圖像編碼來展示:
import?numpy?as?np
import?pandas?as?pd
import?perfplot
perfplot.save(
????"out.png",
????setup=lambda?n:?pd.DataFrame(np.arange(n?*?3).reshape(n,?3)),
????n_range=[2**k?for?k?in?range(25)],
????kernels=[
????????lambda?df:?len(df.index),
????????lambda?df:?df.shape[0],
????????lambda?df:?df[df.columns[0]].count(),
????],
????labels=["len(df.index)",?"df.shape[0]",?"df[df.columns[0]].count()"],
????xlabel="Number?of?rows",
)
問題7:
https://stackoverflow.com/questions/13148429/how-to-change-the-order-of-dataframe-columns
如何改變DataFrame對(duì)象中列的順序?
不羅嗦上代碼,假設(shè)我有如下DataFrame對(duì)象:
import?numpy?as?np
import?pandas?as?pd
df?=?pd.DataFrame(np.random.rand(10,?5))
我增加了一列通過以下方式:
df['mean']?=?df.mean(1)
我如何才能把mean這一列放到前面,比如把mean列放到第一列,保持其他列不動(dòng)?
最佳答案
一個(gè)比較簡(jiǎn)單的方法就是重新給DataFrame對(duì)象傳入一個(gè)你需要次序的列的列表結(jié)構(gòu),請(qǐng)看代碼:
In?[6]:?df
Out[6]:
??????????0?????????1?????????2?????????3?????????4??????mean
0??0.445598??0.173835??0.343415??0.682252??0.582616??0.445543
1??0.881592??0.696942??0.702232??0.696724??0.373551??0.670208
2??0.662527??0.955193??0.131016??0.609548??0.804694??0.632596
3??0.260919??0.783467??0.593433??0.033426??0.512019??0.436653
4??0.131842??0.799367??0.182828??0.683330??0.019485??0.363371
5??0.498784??0.873495??0.383811??0.699289??0.480447??0.587165
6??0.388771??0.395757??0.745237??0.628406??0.784473??0.588529
7??0.147986??0.459451??0.310961??0.706435??0.100914??0.345149
8??0.394947??0.863494??0.585030??0.565944??0.356561??0.553195
9??0.689260??0.865243??0.136481??0.386582??0.730399??0.561593
In?[7]:?cols?=?df.columns.tolist()
In?[8]:?cols
Out[8]:?[0L,?1L,?2L,?3L,?4L,?'mean']
你可以隨意調(diào)整cols的順序,下面是我如何把最后一個(gè)元素調(diào)整到第一個(gè)位置的:
In?[12]:?cols?=?cols[-1:]?+?cols[:-1]
In?[13]:?cols
Out[13]:?['mean',?0L,?1L,?2L,?3L,?4L]
然后重新調(diào)整DataFrame對(duì)象如下:
In?[16]:?df?=?df[cols]??#????OR????df?=?df.ix[:,?cols]
In?[17]:?df
Out[17]:
???????mean?????????0?????????1?????????2?????????3?????????4
0??0.445543??0.445598??0.173835??0.343415??0.682252??0.582616
1??0.670208??0.881592??0.696942??0.702232??0.696724??0.373551
2??0.632596??0.662527??0.955193??0.131016??0.609548??0.804694
3??0.436653??0.260919??0.783467??0.593433??0.033426??0.512019
4??0.363371??0.131842??0.799367??0.182828??0.683330??0.019485
5??0.587165??0.498784??0.873495??0.383811??0.699289??0.480447
6??0.588529??0.388771??0.395757??0.745237??0.628406??0.784473
7??0.345149??0.147986??0.459451??0.310961??0.706435??0.100914
8??0.553195??0.394947??0.863494??0.585030??0.565944??0.356561
9??0.561593??0.689260??0.865243??0.136481??0.386582??0.730399
問題8:
https://stackoverflow.com/questions/19482970/get-a-list-from-pandas-dataframe-column-headers
獲取Pandas中DataFrame列標(biāo)簽的列表
我想要得到一個(gè)由Pandas中DataFrame對(duì)象的列標(biāo)簽組成的列表,這個(gè)DataFrame對(duì)象來自用戶的輸入,因此我不知道有多少列或者他們名字是什么。
舉個(gè)例子:
我有如下DataFrame對(duì)象
>>>?my_dataframe
????y??gdp??cap
0???1????2????5
1???2????3????9
2???8????7????2
3???3????4????7
4???6????7????7
5???4????8????3
6???8????2????8
7???9????9???10
8???6????6????4
9??10???10????7
這是我想要的結(jié)果
>>>?header_list
['y',?'gdp',?'cap']
最佳回答
你可以通過如下方式得到列標(biāo)簽列表:
list(my_dataframe.columns.values)
你也可以簡(jiǎn)單的使用如下方法(Ed Chum的答案之前提過)
list(my_dataframe)
問題9:
https://stackoverflow.com/questions/12555323/how-to-add-a-new-column-to-an-existing-dataframe
如何在已存在的DataFrame對(duì)象中添加一個(gè)新列
我有如下索引的DataFrame對(duì)象,列名均為自定義,且行中是不連續(xù)的數(shù)字:
??????????a?????????b?????????c?????????d
2??0.671399??0.101208?-0.181532??0.241273
3??0.446172?-0.243316??0.051767??1.577318
5??0.614758??0.075793?-0.451460?-0.012493
我現(xiàn)在想在這個(gè)DataFrame對(duì)象中添加一個(gè)新列,‘e’,并且不改變?nèi)魏纹渌慕Y(jié)構(gòu)(例如,新列總是有和這個(gè)DataFrame對(duì)象相同的長(zhǎng)度)
e列會(huì)是如下的樣子:
0???-0.335485
1???-1.166658
2???-0.385571
dtype:?float64
該怎么做?
最佳回答
2017年編輯
正如@Alexdaer在評(píng)論中提到的,目前將Series對(duì)象值添加到一個(gè)DataFrame中的新列里面最佳的方式是通過賦值,代碼如下:
df1?=?df1.assign(e=pd.Series(np.random.randn(sLength)).values)
2015年編輯
有些情況下,使用如下代碼會(huì)產(chǎn)生SettingWithCopyWarning的錯(cuò)誤信息,但是,對(duì)于Pandas為0.16.1的版本還是可以順暢的運(yùn)行這個(gè)代碼的:
>>>?sLength?=?len(df1['a'])
>>>?df1
??????????a?????????b?????????c?????????d
6?-0.269221?-0.026476??0.997517??1.294385
8??0.917438??0.847941??0.034235?-0.448948
>>>?df1['e']?=?pd.Series(np.random.randn(sLength),?index=df1.index)
>>>?df1
??????????a?????????b?????????c?????????d?????????e
6?-0.269221?-0.026476??0.997517??1.294385??1.757167
8??0.917438??0.847941??0.034235?-0.448948??2.228131
>>>?pd.version.short_version
'0.16.1'
SettingWithCopyWarning警告在于提示對(duì)于DataFrame對(duì)象復(fù)制品的無效賦值。當(dāng)然,并不是說你錯(cuò)了,但是到了0.1.30版本它會(huì)提醒你更多合適的方法來滿足需求。然后,如果你得到警告,嘗試使用如下.loc[row_index,col_indexer] = value
>>>?df1.loc[:,'f']?=?pd.Series(np.random.randn(sLength),?index=df1.index)
>>>?df1
??????????a?????????b?????????c?????????d?????????e?????????f
6?-0.269221?-0.026476??0.997517??1.294385??1.757167?-0.050927
8??0.917438??0.847941??0.034235?-0.448948??2.228131??0.006109
>>>?
其實(shí),在Pandas的官方文檔里有更加高效的方法:
原答案:
使用使用源對(duì)象df1的行索引indexes來創(chuàng)建Series對(duì)象:
df1['e']?=?pd.Series(np.random.randn(sLength),?index=df1.index)
問題10
https://stackoverflow.com/questions/15891038/change-column-type-in-pandas
改變DataFrame對(duì)象列的數(shù)據(jù)類型
我想把一個(gè)二維數(shù)組轉(zhuǎn)化成為一個(gè)Pandas的DataFrame對(duì)象,如下所示:
a?=?[['a',?'1.2',?'4.2'],?['b',?'70',?'0.03'],?['x',?'5',?'0']]
df?=?pd.DataFrame(a)
怎樣做才能讓每一列對(duì)應(yīng)它們的應(yīng)有的數(shù)據(jù)類型呢?以剛才的例子來說,第二列和第三列,有沒有什么方法能夠在轉(zhuǎn)化為DataFrame對(duì)象時(shí)候指定它們?yōu)楦↑c(diǎn)數(shù)類型?是不是先建立一個(gè)DataFrame對(duì)象然后遍歷所有的列,然后再改變他們的數(shù)據(jù)類型?我其實(shí)更傾向于動(dòng)態(tài)處理,因?yàn)橛猩习賯€(gè)列的時(shí)候,全部都要一一指定列的數(shù)據(jù)類型太恐怖了。不過我能保證的是每一類的數(shù)據(jù)類型都是一致的。
最佳答案
Pandas中你主要有4中方法來轉(zhuǎn)化類型:
to_numeric() - 提供了安全的非數(shù)字類型到數(shù)字類型的轉(zhuǎn)化方式(同樣可以參考下to_datetime() 和 to_timedelta()方法)
astype() - 幾乎可以轉(zhuǎn)化任何類型數(shù)據(jù)為其他任意數(shù)據(jù)類型(即使沒什么必要這么做)。你還可以使用它去轉(zhuǎn)化分類對(duì)象(很有用哦)
infer_objects() - 一個(gè)可以將存儲(chǔ)Python對(duì)象的對(duì)象列轉(zhuǎn)化為pandas類型的實(shí)用方法
convert_dtypes() - 將DataFrame對(duì)象的列轉(zhuǎn)化為最可能的dtype類型數(shù)據(jù),支持pd.NA(pandas中缺失值的表示方式)
接下來我詳細(xì)闡釋下他們的作用:
1. to_numeric()
這個(gè)方法是轉(zhuǎn)化一個(gè)或者多個(gè)DataFrame列數(shù)據(jù)類型為數(shù)值類型的最佳方法。
這個(gè)函數(shù)會(huì)盡可能嘗試將非數(shù)值對(duì)象(例如strings字符串)轉(zhuǎn)化為整數(shù)或者浮點(diǎn)型。
基本用法: to_numeric()傳入的參數(shù)一般是一個(gè)Series對(duì)象或者一個(gè)DataFrame的列
>>>?s?=?pd.Series(["8",?6,?"7.5",?3,?"0.9"])?#?混合數(shù)值和字符串類型
>>>?s
0??????8
1??????6
2????7.5
3??????3
4????0.9
dtype:?object
>>>?pd.to_numeric(s)?#?將所有數(shù)據(jù)轉(zhuǎn)化為了浮點(diǎn)型
0????8.0
1????6.0
2????7.5
3????3.0
4????0.9
dtype:?float64
As you can see, a new Series is returned. Remember to assign this output to a variable or column name to continue using it: 如上述代碼,最終返回了一個(gè)新的Seris對(duì)象,如果要繼續(xù)使用這個(gè)對(duì)象,你需要添加到一個(gè)新的變量或者列名變量中
轉(zhuǎn)化Series對(duì)象
my_series?=?pd.to_numeric(my_series)
轉(zhuǎn)化一個(gè)DataFrame對(duì)象的a列
df["a"]?=?pd.to_numeric(df["a"])
你也可以使用apply方法將它作用于多個(gè)列:
轉(zhuǎn)化所有列的數(shù)據(jù)類型
df?=?df.apply(pd.to_numeric)?#?轉(zhuǎn)化DataFrame對(duì)象中所有的列的數(shù)據(jù)類型
僅僅轉(zhuǎn)化列‘a(chǎn)’和‘b’
df[["a",?"b"]]?=?df[["a",?"b"]].apply(pd.to_numeric)
只要你的值可以做轉(zhuǎn)換,以上方法足夠了。
錯(cuò)誤處理
如果有些值無法轉(zhuǎn)為數(shù)值型怎么辦?
to_numeric()方法還提供了errors參數(shù)用于讓你將非數(shù)值型數(shù)據(jù)強(qiáng)制轉(zhuǎn)化為NaN值或者簡(jiǎn)單的忽略包含這些數(shù)據(jù)的錯(cuò)誤提示。
例如:
>>>?s?=?pd.Series(['1',?'2',?'4.7',?'pandas',?'10'])
>>>?s
0?????????1
1?????????2
2???????4.7
3????pandas
4????????10
dtype:?object
默認(rèn)情況下如果遇到不可以轉(zhuǎn)化的數(shù)據(jù),就會(huì)報(bào)錯(cuò),上面的例子中它不會(huì)處理字符串‘pandas’
>>>?pd.to_numeric(s)?#?or?pd.to_numeric(s,?errors='raise')
ValueError:?Unable?to?parse?string
相比于失敗,我們可能更希望‘pandas’這個(gè)字符串被轉(zhuǎn)化為缺失值或者異常值。因此我們將這樣的值轉(zhuǎn)化NaN值,通常我們會(huì)通過參數(shù)argument來指定:
>>>?pd.to_numeric(s,?errors='coerce')
0?????1.0
1?????2.0
2?????4.7
3?????NaN
4????10.0
dtype:?float64
第三種處理轉(zhuǎn)化錯(cuò)誤的方法就是忽略掉它們:
>>>?pd.to_numeric(s,?errors='ignore')
#?the?original?Series?is?returned?untouched
最后一個(gè)轉(zhuǎn)化方法在我們要轉(zhuǎn)化整個(gè)DataFrame對(duì)象時(shí)特別有用,尤其時(shí)我們不知道其中的列會(huì)被轉(zhuǎn)化成那種數(shù)值類型,這種情況下,可以使用如下操作:
df.apply(pd.to_numeric,?errors='ignore')
上述函數(shù)的使用會(huì)使我們的DataFrame對(duì)象中的數(shù)值型數(shù)據(jù)轉(zhuǎn)化為數(shù)值型,而非數(shù)值型就保持原有的狀態(tài)(例如:純字符串類型) 向下轉(zhuǎn)型:
默認(rèn)情況下,使用to_numeric()函數(shù)轉(zhuǎn)化數(shù)據(jù)會(huì)得到int64位或者float64位數(shù)據(jù)(或者取決于你的平臺(tái)類型產(chǎn)生數(shù)據(jù)長(zhǎng)度和類型)
這通常是滿足我們需求的,但是假設(shè)現(xiàn)在你需要占用更少的內(nèi)存空間比如float32 或者 int8,該怎么辦呢?
to_numeric()提供了一系列的選項(xiàng)來進(jìn)行向下轉(zhuǎn)型,包括 'integer', 'signed', 'unsigned', 'float'. 下面是一個(gè)整型Series對(duì)象:
>>>?s?=?pd.Series([1,?2,?-7])
>>>?s
0????1
1????2
2???-7
dtype:?int64
向下轉(zhuǎn)型時(shí),指定downcast參數(shù)為‘interger’,便可得到內(nèi)存占用盡可能小的空間來容納這個(gè)對(duì)象。
>>>?pd.to_numeric(s,?downcast='integer')
0????1
1????2
2???-7
dtype:?int8
設(shè)置downcast的浮點(diǎn)型參數(shù),便可以獲得一個(gè)比正常浮點(diǎn)數(shù)小的浮點(diǎn)類型
>>>?pd.to_numeric(s,?downcast='float')
0????1.0
1????2.0
2???-7.0
dtype:?float32
2. astype()
astype函數(shù)能夠使你明確指定你的DataFrame或者Series對(duì)象的數(shù)據(jù)類型為你想要指定的。它是非常靈活的一個(gè)函數(shù),允許你很容易的進(jìn)行數(shù)據(jù)間轉(zhuǎn)化。
基本用法:
只需要調(diào)用該方法指定為你想要的數(shù)據(jù)類型,比如Numpy類型(np.int16),一些Python類型(如:bool),或者特殊的pandas類型(比如categorical類型)。該方法都能夠盡可能的嘗試將他們進(jìn)行轉(zhuǎn)化
接下來是一些使用示例:
轉(zhuǎn)化所有的DataFrame列為int64類型
df?=?df.astype(int)
將‘a(chǎn)’列轉(zhuǎn)化為int64的數(shù)據(jù)類型以及‘b’列轉(zhuǎn)化為混合(complex)數(shù)據(jù)類型
將Series對(duì)象轉(zhuǎn)化為float16類型
s?=?s.astype(np.float16)
將Series對(duì)象轉(zhuǎn)化為Python字符串
s?=?s.astype(str)
將series對(duì)象轉(zhuǎn)化為分類(categorical)類型 - 更多細(xì)節(jié)可以參考官方文檔
s?=?s.astype('category')
你還記得我曾說過astype()會(huì)嘗試去將Series或者DataFrame對(duì)象的值進(jìn)行轉(zhuǎn)化嗎?如果它不能判斷如何轉(zhuǎn)化,系統(tǒng)就會(huì)報(bào)錯(cuò),例如你有NaN值或者inf值,當(dāng)你將它們轉(zhuǎn)化為一個(gè)整數(shù)就會(huì)報(bào)錯(cuò)。
當(dāng)Pandas版本是0.20.0時(shí),這個(gè)錯(cuò)誤可以通過傳入errors=‘ignore’來忽略掉,你原有的數(shù)據(jù)不會(huì)發(fā)生任何改變。
注意: astype()確實(shí)很強(qiáng)大,但是有時(shí)候轉(zhuǎn)化數(shù)值時(shí)也會(huì)發(fā)生錯(cuò)誤。例如:
>>>?s?=?pd.Series([1,?2,?-7])
>>>?s
0????1
1????2
2???-7
dtype:?int64
接下來時(shí)一些位數(shù)比較小的整數(shù),那么把他們轉(zhuǎn)化為沒有符號(hào)的8 個(gè)字節(jié)的類型來省些內(nèi)存空間,會(huì)怎么樣?
>>>?s.astype(np.uint8)
0??????1
1??????2
2????249
dtype:?uint8
這個(gè)轉(zhuǎn)化確實(shí)可行,但是你會(huì)發(fā)現(xiàn)-7被轉(zhuǎn)化成了249
使用pd.to_numeric(s,downcast='unsigned')函數(shù)可以規(guī)避上面的錯(cuò)誤
3. infer_objects()
Pandas的0.21.0版本后引入了方法infer_objects()用來將DataFrame對(duì)象的列轉(zhuǎn)化為一個(gè)對(duì)象的數(shù)據(jù)類型為一個(gè)更為準(zhǔn)確的類型(軟轉(zhuǎn)化)
例如:這里是一個(gè)DataFrame對(duì)象包含兩列對(duì)象類型。其一存放了真實(shí)的數(shù)字類型,另外一個(gè)是字符型的數(shù)字類型,
>>>?df?=?pd.DataFrame({'a':?[7,?1,?5],?'b':?['3','2','1']},?dtype='object')
>>>?df.dtypes
a????object
b????object
dtype:?object
使用infer_objects()你可以把a(bǔ)列轉(zhuǎn)化為int64類型:
>>>?df?=?df.infer_objects()
>>>?df.dtypes
a?????int64
b????object
dtype:?object
‘b'列并沒有被處理因?yàn)樗亲址钦汀H绻阆胱寖闪型瑫r(shí)轉(zhuǎn)化,你可以使用astype(int)方法轉(zhuǎn)化。
4. convert_dtypes()
1.0版本或以上包含了convert_dtypes()函數(shù)用于將Series和DataFrame對(duì)象中的columns轉(zhuǎn)化為最佳的數(shù)據(jù)類型從而支持pd.NA缺失值類型。
這里的’最佳‘指的是最適宜存儲(chǔ)指定數(shù)據(jù)的數(shù)據(jù)類型。例如:如果一個(gè)pandas的對(duì)象中的值全部是整數(shù)類型或者缺失值類型:那么Python整數(shù)類型的列將被轉(zhuǎn)化為Int64類型,而Numpy int32類型的數(shù)值就會(huì)編程Pandas類型的Int32
這里我們有個(gè)示例DataFrame對(duì)象,我們可以得到以下結(jié)果:
>>> df.convert_dtypes().dtypes
a Int64
b string
dtype: object
由于’a‘列存放的是整數(shù)數(shù)值,它可以被轉(zhuǎn)化為Int64類型(這使得它不像int64類型,可以存放缺失值,)
’b‘列包含字符串對(duì)象,因此可以被轉(zhuǎn)化為Pandas的字符串類型。
默認(rèn)情況下,這個(gè)方法只要用于每列中的對(duì)象型數(shù)據(jù)。我可以通過設(shè)置infer_objects=False取消這個(gè)默認(rèn)選項(xiàng)。
>>>?df.convert_dtypes(infer_objects=False).dtypes??????????????????????????
a????object
b????string
dtype:?object
現(xiàn)在’a‘列仍然是一個(gè)對(duì)象列:pandas知道它可以被描述為’整型‘列(內(nèi)部運(yùn)行了infer_dtype方法)但是并沒有準(zhǔn)確的指出它應(yīng)該成為的哪種整型類型。而’b‘列之所以被轉(zhuǎn)化為字符串?dāng)?shù)據(jù)主要是因?yàn)樗蛔R(shí)別為了’字符串‘?dāng)?shù)據(jù)。
關(guān)注螞蟻老師,學(xué)習(xí)更多Pandas干貨知識(shí)!
