我有一个包含高度信息的pandas数据框,我似乎无法弄清楚如何将有些非结构化的信息转换为整数。
我认为解决这个问题的最佳方法是使用正则表达式,但我遇到的主要问题是,当我尝试简化问题以使用正则表达式时,我通常会采用数据框中的第一项(7&# 39; 5.5'')并尝试专门使用正则表达式。由于引号,我似乎不可能将这些数据放在字符串中。所以,我真的很困惑如何解决这个问题。
这是我的数据框:
HeightNoShoes HeightShoes
0 7' 5.5" NaN
1 6' 11" 7' 0.25"
2 6' 7.75" 6' 9"
3 6' 5.5" 6' 6.75"
4 5' 11" 6' 0"
输出应以英寸为单位:
HeightNoShoes HeightShoes
0 89.5 NaN
1 83 84.25
2 79.75 81
3 77.5 78.75
4 71 72
我的下一个选择是将此写入csv并使用excel,但我更愿意学习如何在python / pandas中执行此操作。任何帮助将不胜感激。
答案 0 :(得分:3)
问题的上一个答案是在不使用正则表达式的情况下很好地解决了问题。我会发布这个以防你如何使用你的第一个想法(使用正则表达式)解决问题。
使用正则表达式的方法可以解决这个问题。为了将您拥有的数据(例如7'5.5“)放入Python中的字符串中,您可以转义引号。
例如:
py_str = "7' 5.5\""
这与正则表达式结合使用,可以从输入数据中提取所需信息,以计算输出数据。输入数据由整数(英尺)后跟',空格,然后是浮点数(英寸)组成。这个浮点数由一个或多个数字组成,然后可选地包含一个数字。还有更多的数字。这是一个正则表达式,可以从输入数据中提取英尺和英寸:([0-9]+)' ([0-9]*\.?[0-9]+)"
第一组正则表达式检索脚,第二组检索英寸。下面是python中一个函数的示例,它根据输入数据(如"7' 5.5\""
)返回一个以英寸为单位的float,如果没有有效匹配则返回NaN:
代码:
r = re.compile(r"([0-9]+)' ([0-9]*\.?[0-9]+)\"")
def get_inches(el):
m = r.match(el)
if m == None:
return float('NaN')
else:
return int(m.group(1))*12 + float(m.group(2))
示例:
>>> get_inches("7' 5.5\"")
89.5
您可以将该正则表达式应用于数据中的元素。但是,将您自己的函数映射到数据上的解决方案效果很好。您可能希望了解如何使用原始想法来解决这个问题。
答案 1 :(得分:1)
不使用regex
的一种可能方法是编写自己的函数,并将apply
编辑到您选择的列/系列中。
代码:
import pandas as pd
df = pd.read_csv("test.csv")
def parse_ht(ht):
# format: 7' 0.0"
ht_ = ht.split("' ")
ft_ = float(ht_[0])
in_ = float(ht_[1].replace("\"",""))
return (12*ft_) + in_
print df["HeightNoShoes"].apply(lambda x:parse_ht(x))
输出:
0 89.50
1 83.00
2 79.75
3 77.50
4 71.00
Name: HeightNoShoes, dtype: float64
并不是非常优雅,但它可以轻松完成工作。最重要的是,它很容易调整和理解。
比较与公认的解决方案:
In [9]: import re
In [10]: r = re.compile(r"([0-9]+)' ([0-9]*\.?[0-9]+)\"")
...: def get_inches2(el):
...: m = r.match(el)
...: if m == None:
...: return float('NaN')
...: else:
...: return int(m.group(1))*12 + float(m.group(2))
...:
In [11]: %timeit get_inches("7' 5.5\"")
100000 loops, best of 3: 3.51 µs per loop
In [12]: %timeit parse_ht("7' 5.5\"")
1000000 loops, best of 3: 1.24 µs per loop
parse_ht
的速度提高了一倍多。
答案 2 :(得分:0)
首先创建高度值的数据框
让我们首先设置一个 Pandas 数据框来匹配问题。然后使用 apply 将以英尺和英寸显示的值转换为数值。注意:提问者询问是否可以将这些值转换为整数,但是“HeightNoShoes”列中的第一个值是 7' 5.5" 由于此字符串值以半英寸表示,因此将首先转换为浮点值。然后您可以使用 round 函数在将值转换为整数之前对其进行四舍五入。
# libraries
import pandas as pd
# height data
no_shoes = ['''7' 5.5"''',
'''6' 11"''',
'''6' 7.75"''',
'''6' 5.5" ''',
'''5' 11"''']
shoes = [np.nan,
'''7' 0.25"''',
'''6' 9"''',
'''6' 6.75"''',
'''6' 0"''']
# put height data into a Pandas dataframe
height_data = pd.DataFrame({'HeightNoShoes':no_shoes, 'HeightShoes':shoes})
height_data.head()
接下来使用函数将英尺转换为浮点值
这是一个将英尺和英寸转换为浮点值的函数。
def feet_to_float(cell_string):
try:
split_strings = cell_string.replace('"','').replace("'",'').split()
float_value = float(split_strings[0])+float(split_strings[1])
except:
float_value = np.nan
return float_value
接下来,将该函数应用于数据框中的每一列。
# obtain a copy of the height data
df = height_data.copy()
for col in df.columns:
print(col)
df[col] = df[col].apply(feet_to_float)
df.head()
这是一个函数,用于将 Pandas 列中的浮点值转换为具有 NaN 值的整数值
如果您想将数据帧转换为一列中包含 NaN 值的整数值,您可以使用以下函数和代码。请注意,该函数首先对值进行四舍五入,然后再将它们类型转换为整数。 在四舍五入之前将浮点值类型转换为整数只会截断值。
def float_to_int(cell_value):
try:
return int(round(cell_value,0))
except:
return cell_value
for col in df.columns:
df[col] = df[col].apply(feet_to_float)
注意:Pandas 将包含 NaN 值和整数的列显示为浮点值。
这是将数据框中的单列转换为数值的代码。
df = height_data.copy()
df['HeightNoShoes'] = df['HeightNoShoes'].apply(feet_to_float)
df.head()
这是将单列浮点值转换为整数的方法。请注意,首先对值进行四舍五入很重要。 在四舍五入之前将值类型转换为整数将错误地截断值。
df['HeightNoShoes'] = round(df['HeightNoShoes'],0).astype(int)
df.head()
在标记为 'HeightShoes' 的第二个 Pandas 列中有 NaN 值。上面的 feet_to_float 和 float_to_int 函数都应该能够处理这些。
df = height_data.copy()
df['HeightShoes'] = df['HeightShoes'].apply(feet_to_float)
df['HeightShoes'] = df['HeightShoes'].apply(float_to_int)
df.head()