![](/img/trans.png)
[英]Pandas dataframe .at ValueError : cannot convert string to float
[英]Pandas DataFrame: Cannot convert string into a float
我在pandas數據框中有一個列Column1
,其類型為str
,值的格式如下:
import pandas as pd
df = pd.read_table("filename.dat")
type(df["Column1"].ix[0]) #outputs 'str'
print(df["Column1"].ix[0])
輸出'1/350'
。 所以,這是一個字符串。 我想把它轉換成一個浮點數。
我試過這個:
df["Column1"] = df["Column1"].astype('float64', raise_on_error = False)
但這並沒有將值改為浮點數。
這也失敗了:
df["Column1"] = df["Column1"].convert_objects(convert_numeric=True)
這失敗了:
df["Column1"] = df["Column1"].apply(pd.to_numeric, args=('coerce',))
如何將列“Column1”的所有值轉換為浮點數? 我可以以某種方式使用正則表達式刪除括號嗎?
編輯:
這條線
df["Meth"] = df["Meth"].apply(eval)
有效,但只有我使用它兩次,即
df["Meth"] = df["Meth"].apply(eval)
df["Meth"] = df["Meth"].apply(eval)
為什么會這樣?
您需要計算表達式(例如'1/350')才能獲得結果,您可以使用Python的eval()
函數。
通過在其周圍包裝Panda的apply()
函數,您可以對列中的每個值執行eval()
函數。 例:
df["Column1"].apply(eval)
在解釋文字時,您也可以使用文檔中提到的ast.literal_eval
函數。 更新:這不起作用,因為literal_eval()
的使用仍限於加法和減法( 源 )。
備注:正如在這個問題的其他答案和評論中所提到的,使用eval()
並非沒有風險,因為你基本上執行傳入的任何輸入。換句話說,如果你的輸入包含惡意代碼,你就是給它一個免費通行證。
備選方案:
# Define a custom div function
def div(a,b):
return int(a)/int(b)
# Split each string and pass the values to div
df_floats = df['col1'].apply(lambda x: div(*x.split('/')))
不潔數據的第二種選擇 :
通過使用正則表達式,我們可以刪除任何出現resp的非數字。 在分子之前和分母之后。
# Define a custom div function (unchanged)
def div(a,b):
return int(a)/int(b)
# We'll import the re module and define a precompiled pattern
import re
regex = re.compile('\D*(\d+)/(\d+)\D*')
df_floats = df['col1'].apply(lambda x: div(*regex.findall(x)[0]))
我們會失去一點性能,但好處是即使輸入像'!erefdfs?^dfsdf1/350dqsd qsd qs d'
,我們仍然得到1/350
的值。
性能:
當對具有100.000行的數據幀上的兩個選項進行計時時,第二個選項(使用用戶定義的div
函數)明顯獲勝:
eval
:1循環,最佳3:1.41 s每循環 div
:10個循環,最佳3:159 ms每個循環 re
:1循環,最好是每循環3:275 ms 我討厭提倡使用eval
。 我不想花時間在這個答案上,但我被迫,因為我不想讓你使用eval
。
所以我寫了這個函數,適用於pd.Series
def do_math_in_string(s):
op_map = {'/': '__div__', '*': '__mul__', '+': '__add__', '-': '__sub__'}
df = s.str.extract(r'(\d+)(\D+)(\d+)', expand=True)
df = df.stack().str.strip().unstack()
df.iloc[:, 0] = pd.to_numeric(df.iloc[:, 0]).astype(float)
df.iloc[:, 2] = pd.to_numeric(df.iloc[:, 2]).astype(float)
def do_op(x):
return getattr(x[0], op_map[x[1]])(x[2])
return df.T.apply(do_op)
s = pd.Series(['1/2', '3/4', '4/5'])
do_math_in_string(s)
0 0.50
1 0.75
2 0.80
dtype: float64
do_math_in_string(pd.Series(['1/2', '3/4', '4/5', '6+5', '11-7', '9*10']))
0 0.50
1 0.75
2 0.80
3 11.00
4 4.00
5 90.00
dtype: float64
請不要使用eval
。
您可以通過將eval
應用於列來執行此操作:
data = {'one':['1/20', '2/30']}
df = pd.DataFrame(data)
In [8]: df['one'].apply(eval)
Out[8]:
0 0.050000
1 0.066667
Name: one, dtype: float64
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.