我试图解析csv文件中代表高度的所有单元格,并将小数点后的内容四舍五入以匹配列表中的数字(四舍五入到最接近的英寸)。在将我的头撞在墙上几天之后,这就是我能够开始工作的编码:
import math
import pandas as pd
inch = [.0, .08, .16, .25, .33, .41, .50, .58, .66, .75, .83, .91, 1]
df = pd.read_csv("sample_csv.csv")
def to_number(s):
for index, row in df.iterrows():
try:
num = float(s)
num = math.modf(num)
num = list(num)
for i,j in enumerate(inch):
if num[0] < j:
num[0] = inch[i-1]
break
elif num[0] == j:
num[0] = inch[i]
break
newnum = num[0] + num[1]
return newnum
except ValueError:
return s
df = df.apply(lambda f : to_number(f[0]), axis=1).fillna('')
with open('new.csv', 'a') as f:
df.to_csv(f, index=False)
理想情况下,我想让它解析带有n个标题的整个CSV,而忽略所有字符串并舍入浮点数以匹配列表。有没有简单的方法可以通过Pandas实现呢?并且是否有可能(或一个好主意?)让它编辑现有的excel工作簿,而不是创建一个我必须复制/粘贴的新csv?
任何帮助或建议都将不胜感激,因为我对Pandas并不陌生,这真是太该死了!
答案 0 :(得分:2)
如果包含要解析的数据的样本模拟,帮助会容易得多。根据我的理解,要澄清您未指定的要点
6.14 -> 6 feet, 1 inches
(我隐式地假设通过“向下舍入”,您需要整数底限; ie 6.14英尺是6英尺,0.14 * 12 = 1.68英寸;这是地板面积还是四舍五入到最接近的整数)。 现在,对于以5.1英尺和6.9英尺均匀采样的英尺为单位的随机高度子集,我们可以执行以下操作:
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: df = pd.DataFrame(np.random.uniform(5.1, 6.9, size=(10,3)))
In [4]: df
Out[4]:
0 1 2
0 6.020613 6.315707 5.413499
1 5.942232 6.834540 6.761765
2 5.715405 6.162719 6.363224
3 6.416955 6.511843 5.512515
4 6.472462 5.789654 5.270047
5 6.370964 5.509568 6.113121
6 6.353790 6.466489 5.460961
7 6.526039 5.999284 6.617608
8 6.897215 6.016648 5.681619
9 6.886359 5.988068 5.575993
In [5]: np.fix(df) + np.floor(12*(df - np.fix(df)))/12
Out[5]:
0 1 2
0 6.000000 6.250000 5.333333
1 5.916667 6.833333 6.750000
2 5.666667 6.083333 6.333333
3 6.416667 6.500000 5.500000
4 6.416667 5.750000 5.250000
5 6.333333 5.500000 6.083333
6 6.333333 6.416667 5.416667
7 6.500000 5.916667 6.583333
8 6.833333 6.000000 5.666667
9 6.833333 5.916667 5.500000
我们正在使用np.fix
提取高度值的整数部分。同样,df - np.fix(df)
表示乘以12时以英尺或英寸为单位的小数余数。np.floor
只是将其截断为下面的最接近的英寸,最后除以12所得的测量单位从英寸到英尺
您可以将np.floor
更改为np.round
,以获得四舍五入到最接近英寸的答案,而不是四舍五入到先前的整个英寸。最后,您可以指定输出的精度,以坚持要求从列表中选择小数部分。
In [6]: (np.fix(df) + np.round(12*(df - np.fix(df)))/12).round(2)
Out[6]:
0 1 2
0 6.58 5.25 6.33
1 5.17 6.42 5.67
2 6.42 5.83 6.33
3 5.92 5.67 6.33
4 6.83 5.25 6.58
5 5.83 5.50 6.92
6 6.83 6.58 6.25
7 5.83 5.33 6.50
8 5.25 6.00 6.83
9 6.42 5.33 5.08
答案 1 :(得分:0)
添加其他答案以解决字符串问题:
# Break the dataframe with a string
df = pd.DataFrame(np.random.uniform(5.1, 6.9, size=(10,3)))
df.ix[0,0] = 'str'
# Find out which things can be cast to numerics and put NaNs everywhere else
df_safe = df.apply(pd.to_numeric, axis=0, errors="coerce")
df_safe = (np.fix(df_safe) + np.round(12*(df_safe - np.fix(df_safe)))/12).round(2)
# Replace all the NaNs with the original data
df_safe[df_safe.isnull()] = df[df_safe.isnull()]
df_safe
应该是您想要的。尽管名称如此,但这并不是特别安全,并且可能存在边缘条件,这将是一个问题。