我必须在python中清理输入数据文件。由于拼写错误,数据字段可能包含字符串而不是数字。我想识别所有字符串,并使用pandas用NaN填充这些字段。另外,我想记录这些字段的索引。
最原始的方法之一是循环遍历每个字段并检查它是否为数字,但如果数据很大,则会耗费大量时间。
我的csv文件包含类似于下表的数据:
Country Count Sales
USA 1 65000
UK 3 4000
IND 8 g
SPA 3 9000
NTH 5 80000
.... 假设我在数据中有60,000个这样的行。
理想情况下,我想确定IND行在SALES列下的值无效。有关如何有效地做到这一点的任何建议?
答案 0 :(得分:10)
read_csv
有一个na_values
参数:
na_values
:类似列表或字典,默认None
要识别为NA / NaN的其他字符串。如果dict通过,则特定的每列NA值
df = pd.read_csv('city.csv', sep='\s+', na_values=['g'])
In [2]: df
Out[2]:
Country Count Sales
0 USA 1 65000
1 UK 3 4000
2 IND 8 NaN
3 SPA 3 9000
4 NTH 5 80000
使用pandas.isnull
,您只能在'Sales'
列或'Country'
系列中选择包含NaN的行:
In [3]: df[pd.isnull(df['Sales'])]
Out[3]:
Country Count Sales
2 IND 8 NaN
In [4]: df[pd.isnull(df['Sales'])]['Country']
Out[4]:
2 IND
Name: Country
如果它已经存在于DataFrame中,您可以使用apply
将这些数字字符串转换为整数(使用str.isdigit
):
df = pd.DataFrame({'Count': {0: 1, 1: 3, 2: 8, 3: 3, 4: 5}, 'Country': {0: 'USA', 1: 'UK', 2: 'IND', 3: 'SPA', 4: 'NTH'}, 'Sales': {0: '65000', 1: '4000', 2: 'g', 3: '9000', 4: '80000'}})
In [12]: df
Out[12]:
Country Count Sales
0 USA 1 65000
1 UK 3 4000
2 IND 8 g
3 SPA 3 9000
4 NTH 5 80000
In [13]: df['Sales'] = df['Sales'].apply(lambda x: int(x)
if str.isdigit(x)
else np.nan)
In [14]: df
Out[14]:
Country Count Sales
0 USA 1 65000
1 UK 3 4000
2 IND 8 NaN
3 SPA 3 9000
4 NTH 5 80000
答案 1 :(得分:5)
import os
import numpy as np
import pandas as PD
filename = os.path.expanduser('~/tmp/data.csv')
df = PD.DataFrame(
np.genfromtxt(
filename, delimiter = '\t', names = True, dtype = '|O4,<i4,<f8'))
print(df)
产量
Country Count Sales
0 USA 1 65000
1 UK 3 4000
2 IND 8 NaN
3 SPA 3 9000
4 NTH 5 80000
要查找销售额NaN
的国家/地区,您可以计算
print(y['Country'][np.isnan(y['Sales'])])
产生pandas.Series
:
2 IND
Name: Country
答案 2 :(得分:1)
尝试将'sales'字符串转换为int
,如果形式良好然后继续,如果不是,它会引发我们捕获的ValueError
并替换为该地点支架
bad_lines = []
with open(fname,'rb') as f:
header = f.readline()
for j,l in enumerate(f):
country,count,sales = l.split()
try:
sales_count = int(sales)
except ValueError:
sales_count = 'NaN'
bad_lines.append(j)
# shove in to your data structure
print country,count,sales_count
您可能需要编辑拆分线的行(因为您的示例被复制为空格而不是制表符)。用您想要处理的数据替换打印行。你可能需要用大熊猫NaN来重新'NaN'。
答案 3 :(得分:1)
filename = open('file.csv')
filename.readline()
for line in filename:
currentline = line.split(',')
try:
int(currentline[2][:-1])
except:
print currentline[0], currentline[2][:-1]
IND g
答案 4 :(得分:1)
我建议使用正则表达式:
import re
ss = '''Country Count Sales
USA , 3 , 65000
UK , 3 , 4000
IND , 8 , g
SPA , ju , 9000
NTH , 5 , 80000
XSZ , rob , k3'''
with open('fofo.txt','w') as f:
f.write(ss)
print ss
print
delimiter = ','
regx = re.compile('(.+?(?:{0}))'
'(( *\d+?)| *.+?)'
'( *(?:{0}))'
'(( *\d+?)| *.+?)'
'( *\r?\n?)$'.format(delimiter))
def READ(filepath, regx = regx):
with open(filepath,'rb+') as f:
yield f.readline()
for line in f:
if None in regx.match(line).group(3,6):
g2,g3,g5,g6 = regx.match(line).group(2,3,5,6)
tr = ('%%%ds' % len(g2) % 'NaN' if g3 is None else g3,
'%%%ds' % len(g5) % 'NaN' if g6 is None else g6)
modified_line = regx.sub(('\g<1>%s\g<4>%s\g<7>' % tr),line)
print ('------------------------------------------------\n'
'%r with aberration\n'
'%r modified line'
% (line,modified_line))
yield modified_line
else:
yield line
with open('modified.txt','wb') as g:
g.writelines(x for x in READ('fofo.txt'))
结果
Country Count Sales
USA , 3 , 65000
UK , 3 , 4000
IND , 8 , g
SPA , ju , 9000
NTH , 5 , 80000
XSZ , rob , k3
------------------------------------------------
'IND , 8 , g\r\n' with aberration
'IND , 8 , NaN\r\n' modified line
------------------------------------------------
'SPA , ju , 9000\r\n' with aberration
'SPA , NaN , 9000\r\n' modified line
------------------------------------------------
'XSZ , rob , k3' with aberration
'XSZ , NaN , NaN' modified line