从数据框列中拆分混合数字字符串并将其转换为浮点数
Splitting a mixed number string from a dataframe column and converting it to a float
我有一个数据框,其中有一列字符串是整数和带分数的混合。我想将列 'y' 转换为浮点数。
x y z
0 4 Info
1 8 1/2 Info
2 3/4 Info
3 10 Info
4 4 Info
5 6 1/4 Info
我考虑的逻辑是将列 'y' 拆分为“ ”和“/”,以创建三个单独的列,如下所示。
x base b c z
0 4 0 0 Info
1 8 1 2 Info
2 0 3 4 Info
3 10 0 0 Info
4 4 0 0 Info
5 6 1 4 Info
从这里我可以
def convertReplace(df):
convert = lambda x: float(x)
df['base'].apply(convert)
df['b'].apply(convert)
df['c'].apply(convert)
decimal = lambda x,y: x/y
try:
df['d'] = decimal(df['b'],df['c'])
df['y'] = df['base'] + df['d']
except:
df['y'] = df['base']
return df
这可能有效,但我无法使用 here 找到的方法拆分列。
df = pd.DataFrame(df.y.str.split(' ',1).str.split('/',1).tolist(),columns = ['base','b','c'])
错误提示它每次需要 3 个参数,而参数可能是 1、2 或 3。甚至 this thread 也不使用多个分隔符。
实际数据框有超过 40 万行。效率会很高,但我更感兴趣的是完成它。这个逻辑是正确的还是有更简洁的方法来做到这一点?任何帮助表示赞赏。
您可以试试 fractions 模块。这是一条直线:
import fractions
df['y_float'] = df['y'].apply(lambda frac: float(sum([fractions.Fraction(x) for x in frac.split()])))
这给出:
y z y_float
0 4 Info 4.00
1 8 1/2 Info 8.50
2 3/4 Info 0.75
3 10 Info 10.00
4 4 Info 4.00
5 6 1/4 Info 6.25
[编辑] 修正了负分数和无效文本的版本:
我意识到上述方法不适用于负分数,所以这里考虑到了这一点。事实证明,单行代码会非常棘手!
def get_sign(num_str):
"""
Verify the sign of the fraction
"""
return 1-2*num_str.startswith('-')
def is_valid_fraction(text_str):
"""
Check if the string provided is a valid fraction.
Here I just used a quick example to check for something of the form of the fraction you have. For something more robust based on what your data can potentially contain, a regex approach would be better.
"""
return text_str.replace(' ', '').replace('-', '').replace('/', '').isdigit()
def convert_to_float(text_str):
"""
Convert an incoming string to a float if it is a fraction
"""
if is_valid_fraction(text_str):
sgn = get_sign(text_str)
return sgn*float(sum([abs(fractions.Fraction(x)) for x in text_str.split()]))
else:
return pd.np.nan # Insert a NaN if it is invalid text
现在你将拥有这个:
>>> df['y_float'] = df['y'].apply(lambda frac: convert_to_float(frac))
>>> df
y z y_float
0 4 Info 4.00
1 8 1/2 Info 8.50
2 3/4 Info 0.75
3 10 Info 10.00
4 0 Info 0.00
5 6 1/4 Info 6.25
6 -3 2/5 Info -3.40
7 -4/5 Info -0.80
8 gibberish100 Info NaN
我有一个数据框,其中有一列字符串是整数和带分数的混合。我想将列 'y' 转换为浮点数。
x y z
0 4 Info
1 8 1/2 Info
2 3/4 Info
3 10 Info
4 4 Info
5 6 1/4 Info
我考虑的逻辑是将列 'y' 拆分为“ ”和“/”,以创建三个单独的列,如下所示。
x base b c z
0 4 0 0 Info
1 8 1 2 Info
2 0 3 4 Info
3 10 0 0 Info
4 4 0 0 Info
5 6 1 4 Info
从这里我可以
def convertReplace(df):
convert = lambda x: float(x)
df['base'].apply(convert)
df['b'].apply(convert)
df['c'].apply(convert)
decimal = lambda x,y: x/y
try:
df['d'] = decimal(df['b'],df['c'])
df['y'] = df['base'] + df['d']
except:
df['y'] = df['base']
return df
这可能有效,但我无法使用 here 找到的方法拆分列。
df = pd.DataFrame(df.y.str.split(' ',1).str.split('/',1).tolist(),columns = ['base','b','c'])
错误提示它每次需要 3 个参数,而参数可能是 1、2 或 3。甚至 this thread 也不使用多个分隔符。
实际数据框有超过 40 万行。效率会很高,但我更感兴趣的是完成它。这个逻辑是正确的还是有更简洁的方法来做到这一点?任何帮助表示赞赏。
您可以试试 fractions 模块。这是一条直线:
import fractions
df['y_float'] = df['y'].apply(lambda frac: float(sum([fractions.Fraction(x) for x in frac.split()])))
这给出:
y z y_float
0 4 Info 4.00
1 8 1/2 Info 8.50
2 3/4 Info 0.75
3 10 Info 10.00
4 4 Info 4.00
5 6 1/4 Info 6.25
[编辑] 修正了负分数和无效文本的版本:
我意识到上述方法不适用于负分数,所以这里考虑到了这一点。事实证明,单行代码会非常棘手!
def get_sign(num_str):
"""
Verify the sign of the fraction
"""
return 1-2*num_str.startswith('-')
def is_valid_fraction(text_str):
"""
Check if the string provided is a valid fraction.
Here I just used a quick example to check for something of the form of the fraction you have. For something more robust based on what your data can potentially contain, a regex approach would be better.
"""
return text_str.replace(' ', '').replace('-', '').replace('/', '').isdigit()
def convert_to_float(text_str):
"""
Convert an incoming string to a float if it is a fraction
"""
if is_valid_fraction(text_str):
sgn = get_sign(text_str)
return sgn*float(sum([abs(fractions.Fraction(x)) for x in text_str.split()]))
else:
return pd.np.nan # Insert a NaN if it is invalid text
现在你将拥有这个:
>>> df['y_float'] = df['y'].apply(lambda frac: convert_to_float(frac))
>>> df
y z y_float
0 4 Info 4.00
1 8 1/2 Info 8.50
2 3/4 Info 0.75
3 10 Info 10.00
4 0 Info 0.00
5 6 1/4 Info 6.25
6 -3 2/5 Info -3.40
7 -4/5 Info -0.80
8 gibberish100 Info NaN