iT邦幫忙

1

基礎常用:python 從字串中取出數值

前言

在實作時,常常會把所有資訊存成 csv 檔做紀錄,用 pandas 的 read_csv 讀取後,以 DataFrame 的方式瀏覽,不過這樣內容就會是以「字串」的方式來儲存,如果需要用到儲存的數值時就有點麻煩,所以本篇會介紹一些從字串取出數字的方法。

重點摘錄

方法一:number_from_string.get_nums()
方法二:.isdigit()
方法三:re.findall(r'-?\d+\.?\d*', list)

方法介紹

好用的放在前面~

方法一:現成套件 (number_from_string)

使用 number_from_string 當中的 get_nums()
得到的數字直接是數值型態

安裝指令:

pip install nums_from_string

範例:

# 載入現成套件
import nums_from_string as nfs

# 使用 get_nums() 函數
string_with_number = '[6, 7, 8, 9, 10, 11, 12, 13, 14]'
number_list = nfs.get_nums(string_with_number)

print('Extracted numbers: ', number_list)
print('Type of item in "number_list": ', type(number_list[0]))

>>> Extracted numbers:  [6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> Type of item in "number_list":  <class 'int'>

方法二:isdigit()

把字串中每個字元拆開,依序用 isdigit() 來判斷是不是數字,是的話再看要轉換成什麼數值型態 (可以用 int(), flost()),再儲存到 list 裡面

缺點:
這個方法的問題在於,要依據什麼來分割字串,str.split() 默認設定是根據空格,但如果字串比較複雜這個方法就比較不適合。另外一個直接的問題是,如果以字元為單位來分割的話(如下面範例),非個位數的位數就會被拆開,舊問題就滿嚴重的~

範例:

# 將字串拆開,依序用 isdigit() 來判斷是否為數字
string_with_number = '[3, 4, 5, 6, 7, 8]'
number_list = [int(item) for item in string_with_number if item.isdigit()]

print('Extracted numbers: ', number_list)
print('Type of item in "number_list": ', type(number_list[0]))

>>> Extracted numbers:  [3, 4, 5, 6, 7, 8]
>>> Type of item in "number_list":  <class 'int'>

方法三:正規表達式

這個方法我覺得相對麻煩,但如果要篩選的情況比較特別,想要設定一些條件的話,這個方法滿值得試試看~

正規表達式簡介

正規表達式的基本概念就是:[某個或某類匹配內容] 加上 [設定匹配出現的情況]

一些基本正規表達式的意思如下:
* 表示比對內容可以出現 0 次或多次
? 表示比對內容可以出現 0 或 1 次
+ 表示比對內容至少出現 1 次,沒有上限
\ 則是可以粗分成兩種來說明:

  1. 讓有特殊功能的符號,變成單純表示字串的符號(例如:. 表示除了 '\n' 之外的任何字元,但是 . 就變成是匹配小數點)
  2. 或者是表示特殊序列(例如:\d 就代表數字 0 到 9)

下面直接來解釋參考文獻中舉的例子:
針對 '-?\d+\.?\d*' 這一串來做個解析,來看為什麼這一串可以幫助我們找到字串中的數字:

  • -?:負號出現0次或1次
  • \d+:0 到 9 至少出現一次
  • \.?\d*:這邊表有小數點的情況考慮進去(小數點可以出現 0 次或 0 次),以及後面可以再接數字(數字可以出現 0 次或多次)

參考文獻中舉的例子:

# 先載入正規表達式的套件 re (Regular Expressions)
import re

# 使用 re.findall()
sentence = 'Extract 100 , 100.45 and 10000 from this string'
s = [float(s) for s in re.findall(r'-?\d+\.?\d*', sentence)]
print(s)

>>> [100.0, 100.45, 10000.0]

謝謝大家看到這邊,如果有錯誤的地方,或是想討論的,歡迎在下方留言~

References


尚未有邦友留言

立即登入留言