0

所以我有一个相当大的数据集,看起来像这样:

data=[['O', '3C-1', '100', '100', '67.848600000000005', '0.00021722920782039196', '3.4565635', '1.3', '0.7', '0.38673693', '0.618034', '30.0', '-2.0097724299999977'],
['I', '1C-2', '150', '150', '101.77200000000001', '9.6548022169817182e-05', '3.46454077', '1.3', '0.7', '-1.77373911', '-1.70838786', '30.0', '-1.8860072499999994'],
['O', '3C-2', '250', '250', '169.62', '3.4757287981134192e-05', '3.48710222', '1.3', '0.7', '-6.81997504', '-3.94866255', '30.0', '-1.5686071800000005'],
['O', '3C-2', '500', '500', '339.23899999999998', '8.6893732236788835e-06', '3.23954068', '1.3', '0.7', '19.05924395', '2.15260466', '30.0', '-1.0255009299999993']]

然后我有一个看起来像这样的定义:

def mdata(a=None,b=None,c=None,d=None):
    filt=[]
    for num,a in enumerate([a,b,c,d]):
        if a==None: continue
        filt.append([a,num])
    data=creader(open(stuff.csv'))
    for a,num in filt:
        data=[x for x in data if a in x[num]]
    for a in data: print a

a,b,c,d 处理数据集的前四列。因此,如果我调用 mdata() 它会返回整个数据集,但如果指定 data(a='O') 它只会返回第一列有 O 的数据。

除了列 c 和 d 之外,这工作正常,因为它们应该是整数。例如,如果我指定 mdata(c='10'),我将获得第三列包含 10 的所有数据集(100、5103 等)。我可以在这里设置一个条件来有条件地搜索字符串或将有问题的数据转换为 int,但我无法使条件正确,而且这似乎也是一种非常糟糕的方法。如何改进?

4

2 回答 2

2

您可以子类list化以添加将列名映射到每个元素的子元素的能力,然后提供过滤机制。以下将像常规列表一样工作,除了如果元素没有len与列表期望元素具有的列数相同的元素,您将无法添加,并且您将能够迭代其中过滤的元素,如您所愿,使用filtered_by(). 提供给初始化程序的任何列名都将是filtered_by().

class FilterableList(list):

    def __init__(self, column_names, initial_data=None):
        if initial_data is not None:
            list.__init__(self, initial_data)
        else:
            list.__init__(self)
        self.column_names = column_names

    def __setitem__(self, index, value):
        if len(value) != len(self.column_names):
            raise ValueError('Rows must have the correct number of columns.')
        list.__setitem__(self, index, value)

    def append(self, value):
        if len(value) != len(self.column_names):
            raise ValueError('Rows must have the correct number of columns.')
        list.append(self, value)

    def extend(self, values):
        for value in values:
            self.append(value)

    def filtered_by(self, **filters):
        try:
            filters = [(self.column_names.index(filter[0]), filter[1]) for filter in filters.iteritems()]
        except ValueError:
            raise ValueError('Tried to apply filter with invalid column name.')
        for row in self:
            for index, value in filters:
                if row[index] != value:
                    continue
                yield row

data = FilterableList(('a', 'b', 'c', 'd'))
data.extend(((1,2,3,4), (2,2,5,6), (3,4,7,8)))
for row in data.filtered_by(b=2, c=5):
    print row
于 2013-01-18T18:32:19.867 回答
2

我强烈建议您查看pandas库。

这就是它使事情变得非常容易的事情。

首先,加载数据:

>>> data = pd.read_csv("op.csv", index_col=False)
>>> data
   0     1    2    3         4         5         6    7    8          9        10  11        12
0  O  3C-1  100  100   67.8486  0.000217  3.456564  1.3  0.7   0.386737  0.618034  30 -2.009772
1  I  1C-2  150  150  101.7720  0.000097  3.464541  1.3  0.7  -1.773739 -1.708388  30 -1.886007
2  O  3C-2  250  250  169.6200  0.000035  3.487102  1.3  0.7  -6.819975 -3.948663  30 -1.568607
3  O  3C-2  500  500  339.2390  0.000009  3.239541  1.3  0.7  19.059244  2.152605  30 -1.025501

选择一列,找出哪些值是"O"

>>> data['0']
0    O
1    I
2    O
3    O
Name: 0
>>> data['0'] == "O"
0     True
1    False
2     True
3     True
Name: 0

只获取那些行:

>>> data[data['0'] == "O"]
   0     1    2    3         4         5         6    7    8          9        10  11        12
0  O  3C-1  100  100   67.8486  0.000217  3.456564  1.3  0.7   0.386737  0.618034  30 -2.009772
2  O  3C-2  250  250  169.6200  0.000035  3.487102  1.3  0.7  -6.819975 -3.948663  30 -1.568607
3  O  3C-2  500  500  339.2390  0.000009  3.239541  1.3  0.7  19.059244  2.152605  30 -1.025501

按第一个值对行进行分组:

>>> for val, rows in data.groupby("0"):
...     print val
...     print rows
...     
I
   0     1    2    3        4         5         6    7    8         9        10  11        12
1  I  1C-2  150  150  101.772  0.000097  3.464541  1.3  0.7 -1.773739 -1.708388  30 -1.886007
O
   0     1    2    3         4         5         6    7    8          9        10  11        12
0  O  3C-1  100  100   67.8486  0.000217  3.456564  1.3  0.7   0.386737  0.618034  30 -2.009772
2  O  3C-2  250  250  169.6200  0.000035  3.487102  1.3  0.7  -6.819975 -3.948663  30 -1.568607
3  O  3C-2  500  500  339.2390  0.000009  3.239541  1.3  0.7  19.059244  2.152605  30 -1.025501

等等:

>>> data[data['0'] == "O"]["4"]
0     67.8486
2    169.6200
3    339.2390
Name: 4
>>> data[data['0'] == "O"]["4"].mean()
192.23586666666665

这让我的生活变得轻松多了。

于 2013-01-18T21:47:31.943 回答