如何解析一个简单的csv文件?

时间:2015-05-16 10:43:57

标签: python python-2.7 parsing csv

我有一个像这样的简单CSV文件:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Note ,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
1,,,,,X,,,,,,,,X,,,,,,,,X,,,,,,,,X,,,
2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

我需要将其解析为包含 1 -s的二维数组,其中X为 0 ,否则忽略标题/额外行。

在阅读 csv 模块上的文档后,我写了一个简单的脚本,如下所示:

import csv

csvfile = open('input.csv', 'rb')
reader = csv.reader(csvfile,dialect='excel', delimiter=' ', quotechar='|')

data = []

rowCount = 0
for row in reader:
    if(rowCount > 2): #skip first 3 rows (2 empty and 1 label)
        dataRow = []
        for i in xrange(1,len(row[0])):#skip 1st label column
            dataRow.append(1 if row[0][i] == 'X' else 0) #append 1s for X, 0s otherwise
        data.append(dataRow)
    rowCount += 1

print data

这给了我预期的输出:

[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

代表

,,,,,X,,,,,,,,X,,,,,,,,X,,,,,,,,X,,,

三元条件可以写成ord(row[0][i])/88,但是可以将每个字符串行映射到1和0的整数行吗?

是否有更多' pythonic'写这个的方式?

4 个答案:

答案 0 :(得分:6)

您应该使用delimiter=','

reader = csv.reader(csvfile, dialect='excel', delimiter=',', quotechar='|')

实际上:

dialect='excel', delimiter=','是默认值,您的示例文件不需要quotechar='|'(如果需要,请保留)。所以这个更短:

reader = csv.reader(csvfile)

丢掉前三行:

[next(reader) for _ in range(3)]

阅读所有专栏:

data = [[1 if entry=='X' else 0 for entry in row[1:]] for row in reader]

这相当于:

data = []
for row in reader:
    data.append([1 if entry=='X' else 0 for entry in row[1:]])

当然,请在dedent后自动关闭打开文件:

with open('input.csv', 'rb‘) as csvfile:
    # Put the rest of the algorithm here.
# The file is closed automatically just because continuing detended. 

这是context manager的主要示例。

全部放在一起:

import csv

with open('input.csv', 'rb') as csvfile:
    reader = csv.reader(csvfile)
    [next(reader) for _ in range(3)]
    data = [[1 if entry=='X' else 0 for entry in row[1:]] for row in reader]

答案 1 :(得分:4)

首先,跳过三行可以像:

for _ in range(3):
    next(reader)

然后您可以在其余部分使用list comprehension

data = [[int(cell == 'X') for cell in line[1:]] for line in reader]

这为您提供了一个列表列表:

>>> data
[[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

如果效率很重要并且线条较长,则使用itertools.islice可以在不创建新列表的情况下对每一行进行切片。

请注意,您的delimiterquotechar设置似乎与示例文件不匹配,因此您可能需要仔细检查一下。

答案 2 :(得分:1)

有一件事我想添加到@jonrsharpe的答案。

使用文件的Pythonic方式如下。 这将在您完成计算时为您关闭文件

angular.module('ArtistController', []).controller('ArtistController', ['$scope', 'Artist', '$location', '$routeParams',
function ($scope, Artist, $location, $routeParams) {

    $scope.getArtistInfo = function (params) {   
        $scope.artist = Artist.getArtistInfo(params);
    }

    $scope.params = $routeParams;
}
]);

答案 3 :(得分:0)

答:尽量避免管理费用......聪明的读者来自 numpy.genfromtxt()

DATA = np.genfromtxt(   aFH,                  # aFH = open( <aFileNAME>, "r" )
                        #kiprows        = 1,  # DeprecationWarning: The use of `skiprows` is deprecated, it will be removed in numpy 2.0.
                        skip_header     = 3,  # twice "..." + "Note,1,2,3.."
                        delimiter       = ",",
                        converters      = { 1:  lambda aString: mPlotDATEs.date2num( datetime.datetime.strptime( aString[1:-1], "%m/%d/%y %H:%M" ) ),
                                            0:  lambda aString: float(                                           aString[1:-1] )
                                            } # left as an example of powers the genfromtxt()'s inline conversters create
                        )
print "DATA has shape of ", DATA.shape

aFH.close()

converters (asDict)是关键字(指定每列) - 即可以将 X -s后处理为< strong> 1 -s和 isBlank -s到 0 -s

+其他好处

根据 numpy ,任何严重的数字运算都是可见的或不可见的。因此,导入模块的足迹不会导入 pandas (非常智能且非常强大),只需导入文本行而无需进一步使用高级{{ 1}}能力。

此外,如果您的 DataFrame 变得越来越大,您可能会从其他更智能的 numpy 功能中受益。从您的示例数据中可以看出,这是使用 SPARSE-MATRICE 的典型情况,您不需要支付与处理差不多相关的巨额开销 - -cells( DATA.size -s)。

这可能会给你提供比 bool -ean-MASK数组更加紧凑的内存解决方案,它仍然在0-cell-s上花费超过几位网格化( DENSE -MATRIX)。

问:还有更多 - 0 - ic方法吗?

希望这不会引发火焰战争。因此,作为简约视图,我们假设 python -loops被避免(第一次加 - 正式和性能方面),单线 - 民粹主义者可能也很高兴,因为整个导入过程需要一行(有点健谈,但仍有一行...... SLOC-line 如果有人真正关心:o))。 最后 for -inliners非常聪明且功能强大 lambda -ic non-plus-ultra(get爱上他们,因为他们都给你巨大的力量,所以,所以,所以, python -ic(虽然原则上这些“查克诺里斯”的代码起源于LISP在上世纪50年代后期开发的关于高效软件设计的科学))