在 xcel 到制表符分隔文件转换期间将浮点数转换为整数
Convert Float to Integer During xcel to Tab Delimited File Conversion
我编写了以下将 .xlsx
文件转换为 .txt
制表符分隔文件的方法。
import sys
import xlrd
import csv
def xlsx_to_tab(self, inFile):
''' Convert an xlsx file to a tab delimited file. '''
excel_file = xlrd.open_workbook(inFile)
worksheet = excel_file.sheet_names()[0]
sh = excel_file.sheet_by_name(worksheet)
extentPos = inFile.rfind('.')
tab_file = open(inFile[:extentPos] + '.txt', 'w')
writetab = csv.writer(tab_file, delimiter='\t', quoting=csv.QUOTE_ALL)
for row in range(sh.nrows):
writetab.writerow(sh.row_values(row))
tab_file.close()
此方法在文件格式之间成功转换,但是,原始 excel 文件中看似整数的内容在 .txt
文件输出中输出为浮点数。
我知道这可能与 excel 中的单元格格式设置有关。话虽如此,我想在此脚本中处理此问题,因为我想将文件中的元素明确定义为具有 int()
的整数,而不是之前检查和更改所有 excel 文件手会很乏味。
此方法逐行处理文件。有没有办法检索每一行中的单个元素,以便将它们类型转换为整数?
This question 类解决问题:
但展示了如何一次对一个值执行此操作,而不是对一整列值执行此操作。
更清楚一点,我试图将单个列转换为整数,但不是全部。所以只需要转换每一行的部分元素。
数字列是第 1、3 和 5 列
使用列表理解将行的元素转换为 int
,然后再将它们写入新文件:
for row in range(sh.nrows):
new_row = [int(x) for x in sh.row_values(row)]
writetab.writerow(new_row)
编辑:根据下面 OP 的新评论,您需要做的(虽然不漂亮)是:
int_columns = [1, 3, 5]
for row in range(sh.nrows):
new_row = sh.row_values(row)
for col in int_columns:
new_row[col] = int(new_row[col])
writetab.writerow(new_row)
我建议您稍微更改一下命名。在最外层的循环中,您迭代整数,但您将变量命名为 row
。我会这样写:
int_columns = [1, 3, 5]
for i in range(sh.nrows):
row = sh.row_values(i)
for col in int_columns:
row[col] = int(new_row[col])
writetab.writerow(row)
你可以这样做:
for row in range(sh.nrows):
new_row = [int(x) if i in {1,3,5} else x for i, x in
enumerate(sh.row_values(row), start=1)]
writetab.writerow(new_row)
也可以考虑使用此检查单元格是否为 float/integer/text 并使用带有自定义函数的 map 进行转换,如下所示:
def convert_int_or_string(n):
try:
float(n)
assert str(n).lower() != 'nan'
return int(float(n))
except (ValueError, AssertionError):
return n
test_row
['3.14',
'nan',
'12.143141234',
'hello',
'0.13989402028',
'world',
'0.26575558139',
'11',
'0.919189932407',
'!']
map(convert_int_or_string, test_row)
[3, 'nan', 12, 'hello', 0, 'world', 0, 11, 0, '!']
在您的模块中添加此 convert_int_or_string
函数并将此行更改为:
writetab.writerow(map(convert_int_or_string, sh.row_values(row)))
我编写了以下将 .xlsx
文件转换为 .txt
制表符分隔文件的方法。
import sys
import xlrd
import csv
def xlsx_to_tab(self, inFile):
''' Convert an xlsx file to a tab delimited file. '''
excel_file = xlrd.open_workbook(inFile)
worksheet = excel_file.sheet_names()[0]
sh = excel_file.sheet_by_name(worksheet)
extentPos = inFile.rfind('.')
tab_file = open(inFile[:extentPos] + '.txt', 'w')
writetab = csv.writer(tab_file, delimiter='\t', quoting=csv.QUOTE_ALL)
for row in range(sh.nrows):
writetab.writerow(sh.row_values(row))
tab_file.close()
此方法在文件格式之间成功转换,但是,原始 excel 文件中看似整数的内容在 .txt
文件输出中输出为浮点数。
我知道这可能与 excel 中的单元格格式设置有关。话虽如此,我想在此脚本中处理此问题,因为我想将文件中的元素明确定义为具有 int()
的整数,而不是之前检查和更改所有 excel 文件手会很乏味。
此方法逐行处理文件。有没有办法检索每一行中的单个元素,以便将它们类型转换为整数?
This question 类解决问题:
但展示了如何一次对一个值执行此操作,而不是对一整列值执行此操作。
更清楚一点,我试图将单个列转换为整数,但不是全部。所以只需要转换每一行的部分元素。
数字列是第 1、3 和 5 列
使用列表理解将行的元素转换为 int
,然后再将它们写入新文件:
for row in range(sh.nrows):
new_row = [int(x) for x in sh.row_values(row)]
writetab.writerow(new_row)
编辑:根据下面 OP 的新评论,您需要做的(虽然不漂亮)是:
int_columns = [1, 3, 5]
for row in range(sh.nrows):
new_row = sh.row_values(row)
for col in int_columns:
new_row[col] = int(new_row[col])
writetab.writerow(new_row)
我建议您稍微更改一下命名。在最外层的循环中,您迭代整数,但您将变量命名为 row
。我会这样写:
int_columns = [1, 3, 5]
for i in range(sh.nrows):
row = sh.row_values(i)
for col in int_columns:
row[col] = int(new_row[col])
writetab.writerow(row)
你可以这样做:
for row in range(sh.nrows):
new_row = [int(x) if i in {1,3,5} else x for i, x in
enumerate(sh.row_values(row), start=1)]
writetab.writerow(new_row)
也可以考虑使用此检查单元格是否为 float/integer/text 并使用带有自定义函数的 map 进行转换,如下所示:
def convert_int_or_string(n):
try:
float(n)
assert str(n).lower() != 'nan'
return int(float(n))
except (ValueError, AssertionError):
return n
test_row
['3.14',
'nan',
'12.143141234',
'hello',
'0.13989402028',
'world',
'0.26575558139',
'11',
'0.919189932407',
'!']
map(convert_int_or_string, test_row)
[3, 'nan', 12, 'hello', 0, 'world', 0, 11, 0, '!']
在您的模块中添加此 convert_int_or_string
函数并将此行更改为:
writetab.writerow(map(convert_int_or_string, sh.row_values(row)))