簡體   English   中英

Pandas DataFrame:無法將字符串轉換為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM