用字符

时间:2018-04-29 18:46:16

标签: python arrays string numpy sub-array

我有一个文本文件:

0.01 1 0.1 1 10 100 a
0.02 3 0.2 2 20 200 b
0.03 2 0.3 3 30 300 c
0.04 1 0.4 4 40 400 d

我将其作为列表A读取,然后转换为numpy数组,即:

>>> A
array([['0.01', '1', '0.1', '1', '10', '100', 'a'],
       ['0.02', '3', '0.2', '2', '20', '200', 'b'],
       ['0.03', '2', '0.3', '3', '30', '300', 'c'],
       ['0.04', '1', '0.4', '4', '40', '400', 'd']], 
      dtype='|S4')

我只想提取一个由B组成的子数组A,只要它的第4个条目低于30,就应该看起来像这样:

B = array([['0.01', '1', '0.1', '1', '10', '100', 'a'],
           ['0.02', '3', '0.2', '2', '20', '200', 'b']])

在处理数组时,我通常只做B = A[A[:,4]<30],但在这种情况下(可能是由于存在我从未使用过的字符/字符串),它不起作用,给出我这个:

>>> A[A[:,4]<30]
array(['0.01', '1', '0.1', '1', '10', '100', 'a'], 
      dtype='|S4')

我无法弄清楚原因。我没有处理我的代码,我不认为我可以将所有这些转换为结构或词典:任何建议用numpy数组做这个吗?非常感谢你提前!

2 个答案:

答案 0 :(得分:2)

您必须将intint

进行比较
A[A[:,4].astype(int)<30]

strstr

A[A[:,4]<'30'] 

但是,请注意后者可以在您的特定示例中使用,但通常不会工作,因为您正在比较str顺序(例如,'110' < '30'返回True,但110 < 30返回False

numpy会推断出你的元素&#39;您的数据中的类型。在这种情况下,它将type = '|S4'归因于您的元素,这意味着它们是长度为4的字符串。这可能是基础C代码的结果(它增强了numpy&#39}性能)要求元素具有固定类型。

为了说明这种差异,请检查以下代码:

>>> np.array([['0.01', '1', '0.1', '1', '10', '100', 'a']])
array(['0.01', '1', '0.1', '1', '10', '100', 'a'], dtype='|S4')

长度为4的字符串的推断类型,即元素的最大长度(在elem 0.01中)。现在,如果您明确地定义它来保存常规类型对象,它将执行您想要的操作

>>> np.array([[0.01, 1, 0.1, 1, 10, 100, 'a']], dtype=object)
array([0.01, 1, 0.1, 1, 10, 100, 'a'], dtype=object)

并且您的代码A[A[:,4]<30]可以正常运行。

有关详细信息, this 是一个非常完整的指南

答案 1 :(得分:1)

In [86]: txt='''0.01 1 0.1 1 10 100 a
    ...: 0.02 3 0.2 2 20 200 b
    ...: 0.03 2 0.3 3 30 300 c
    ...: 0.04 1 0.4 4 40 400 d'''
In [87]: A = np.genfromtxt(txt.splitlines(), dtype=str)
In [88]: A
Out[88]: 
array([['0.01', '1', '0.1', '1', '10', '100', 'a'],
       ['0.02', '3', '0.2', '2', '20', '200', 'b'],
       ['0.03', '2', '0.3', '3', '30', '300', 'c'],
       ['0.04', '1', '0.4', '4', '40', '400', 'd']], dtype='<U4')
In [89]: A[:,4]
Out[89]: array(['10', '20', '30', '40'], dtype='<U4')

genfromtxt,默认情况下尝试制作浮点数。但在这种情况下,字符列将为nan。相反,我指定了str dtype。

因此,数字测试需要将列转换为数字:

In [90]: A[:,4].astype(int)
Out[90]: array([10, 20, 30, 40])
In [91]: A[:,4].astype(int)<30
Out[91]: array([ True,  True, False, False])

在这种情况下,字符串比较也有效:

In [99]: A[:,4]<'30'
Out[99]: array([ True,  True, False, False])

或者,如果我们使用dtype = None,它会按列推断dtype并生成结构化数组:

In [93]: A1 = np.genfromtxt(txt.splitlines(), dtype=None,encoding=None)
In [94]: A1
Out[94]: 
array([(0.01, 1, 0.1, 1, 10, 100, 'a'), (0.02, 3, 0.2, 2, 20, 200, 'b'),
       (0.03, 2, 0.3, 3, 30, 300, 'c'), (0.04, 1, 0.4, 4, 40, 400, 'd')],
      dtype=[('f0', '<f8'), ('f1', '<i8'), ('f2', '<f8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8'), ('f6', '<U1')])

现在我们可以按名称选择一个字段,并测试它:

In [95]: A1['f4']
Out[95]: array([10, 20, 30, 40])

无论哪种方式,我们都可以根据True / False掩码或相应的行索引选择行:

In [96]: A[[0,1],:]
Out[96]: 
array([['0.01', '1', '0.1', '1', '10', '100', 'a'],
       ['0.02', '3', '0.2', '2', '20', '200', 'b']], dtype='<U4')

In [98]: A1[[0,1]]     # A1 is 1d
Out[98]: 
array([(0.01, 1, 0.1, 1, 10, 100, 'a'), (0.02, 3, 0.2, 2, 20, 200, 'b')],
      dtype=[('f0', '<f8'), ('f1', '<i8'), ('f2', '<f8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8'), ('f6', '<U1')])