【问题标题】:cannot perform reduce with flexible type无法使用灵活类型执行 reduce
【发布时间】:2017-09-12 12:52:04
【问题描述】:

我有这个数据集:

           Game1    Game2   Game3   Game4     Game5

Player1       2        6        5       2        2

Player2       6        4        1       8        4

Player3       8        3        2       1        5

Player4       4        9        4       7        9

我想计算每个玩家5场比赛的总和

这是我的代码:

import csv
f=open('Games','rb')
f=csv.reader(f,delimiter=';')
lst=list(f)
lst
import numpy as np
myarray = np.asarray(lst)
x=myarray[1,1:] #First player
y=np.sum(x)

我遇到错误“无法使用灵活类型执行缩减”。我对 python 非常陌生,我需要你的帮助。

谢谢

【问题讨论】:

  • 您应该显示实际的 csv 文件,即包含 ; 分隔符的文件。否则,您会让我们猜测dataset 是如何编写的。 x 可能是一个字符串数组,因为您的代码中没有任何内容将字符串转换为数字。

标签: python python-2.7 numpy


【解决方案1】:

只要您熟悉数据类型,您仍然可以使用结构化数组。由于您的数据集非常小,因此当您的 dtype 统一但已命名时,以下示例可以作为将 numpy 与列表推导结合使用的示例

dt = [('Game1', '<i4'), ('Game2', '<i4'), ('Game3', '<i4'),
      ('Game4', '<i4'), ('Game5', '<i4')]
a = np.array([(2, 6, 5, 2, 2),
              (6, 4, 1, 8, 4),
              (8, 3, 2, 1, 5),
              (4, 9, 4, 7, 9)], dtype= dt)

nms = a.dtype.names
by_col = [(i, a[i].sum()) for i in nms if a[i].dtype.kind in ('i', 'f')]
by_col
[('Game1', 20), ('Game2', 22), ('Game3', 12), ('Game4', 18), ('Game5', 20)]

by_row = [("player {}".format(i), sum(a[i])) for i in range(a.shape[0])]
by_row
[('player 0', 17), ('player 1', 23), ('player 2', 19), ('player 3', 33)]

在此示例中,为每个列名称单独获取每个总和将是一件非常痛苦的事情。这就是 ... a[i] for i in nms 位的用处,因为名称列表是由 nms = a.dtype.names 检索的。 由于您正在执行“求和”,因此您希望将求和限制为仅整数和浮点类型,因此 a[i].dtype.kind 部分。

按行求和同样简单,但您会注意到我没有使用这种语法,而是使用了稍微不同的语法来避免错误消息

a[0].sum()  # massive failure
....snip out huge error stuff...
TypeError: cannot perform reduce with flexible type
# whereas, this works....
sum(a[0])   # use list/tuple summation

也许“灵活”的数据类型名不副实。 因此,如果这是您的数据进入的方式,您仍然可以使用结构化和重新排列。您可以通过切片和更改 dtypes 以适应您的目的来熟练地简单地重新格式化您的数据。例如,由于您的数据类型都相同,并且您没有庞大的数据集,那么您可以使用多种方法转换为简单的结构化数组。

b = np.array([list(a[i]) for i in range(a.shape[0])])
b
array([[2, 6, 5, 2, 2],
       [6, 4, 1, 8, 4],
       [8, 3, 2, 1, 5],
       [4, 9, 4, 7, 9]])

b.sum(axis=0)
array([20, 22, 12, 18, 20])

b.sum(axis=1)
array([17, 23, 19, 33])

因此,在处理结构化数组时,您有很多选择,取决于您是需要在纯 python、numpy、pandas 还是混合中工作,那么您应该熟悉所有选项。

附录

作为捷径,我没有提到对本质上结构化但具有相同 dtype 的数组进行“视图”。在上述情况下,产生按行或按列进行简单数组计算的要求的简单方法如下... 制作了数组的副本,但不是必需的

b = a.view(np.int32).reshape(len(a), -1)
b
array([[2, 6, 5, 2, 2],
       [6, 4, 1, 8, 4],
       [8, 3, 2, 1, 5],
       [4, 9, 4, 7, 9]])
b.dtype
dtype('int32')

b.sum(axis=0)
array([20, 22, 12, 18, 20])

b.sum(axis=1)
array([17, 23, 19, 33])

【讨论】:

    【解决方案2】:

    使用 numpy 的复杂之处在于有两个错误来源(以及要阅读的文档),即 python 本身以及 numpy。

    我相信您的问题是您正在使用所谓的structured (numpy) array

    考虑以下示例:

    >>> import numpy as np
    >>> a = np.array([(1,2), (4,5)],  dtype=[('Game 1', '<f8'), ('Game 2', '<f8')])
    >>> a.sum()
    TypeError: cannot perform reduce with flexible type
    

    现在,我首先选择我要使用的数据:

    >>> import numpy as np
    >>> a = np.array([(1,2), (4,5)],  dtype=[('Game 1', '<f8'), ('Game 2', '<f8')])
    >>> a["Game 1"].sum()
    5.0
    

    这正是我想要的。

    也许您会考虑使用pandas(python 库),或者将语言更改为R


    个人意见

    尽管“numpy”确实是一个强大的库,但我仍然避免将它用于数据科学和其他程序围绕“灵活”数据类型设计的“活动”。就我个人而言,当我需要一些快速且可维护的东西时(很容易编写“面向未来的代码”),我会使用 numpy,但我没有时间编写 C 程序。

    就 Pandas 而言,它对我们“Python 黑客”来说很方便,因为它是“用 Python 实现的 R 数据结构”,而“R”(显然)是一种全新的语言。我个人使用 R,因为我认为 Pandas 正在快速发展,这使得编写“考虑未来的代码”变得困难。


    正如评论中所建议的(我相信@jorijnsmit),对于“简单”的情况,不需要引入大的依赖项,例如熊猫。下面的简约示例同时兼容 Python 2 和 3,它使用“典型”Python 技巧来处理问题数据。

    import csv
    
    ## Data-file
    data = \
    '''
           , Game1, Game2,   Game3,   Game4,   Game5
    Player1,  2,    6,       5,       2,     2
    Player2,  6,      4 ,      1,       8,      4
    Player3,  8,     3 ,      2,    1,     5
    Player4,  4,  9 ,   4,     7,    9
    '''
    
    # Write data to file
    with open('data.csv', 'w') as FILE:
        FILE.write(data)
    
    print("Raw data:")
    print(data)
    
    # 1) Read the data-file (and strip away spaces), the result is data by column:
    with open('data.csv','rb') as FILE:
      raw = [ [ item.strip() for item in line] \
                          for line in list(csv.reader(FILE,delimiter=',')) if line]
    
    print("Data after Read:")
    print(raw)
    
    # 2) Convert numerical data to integers ("float" would also work)
    for (i, line) in enumerate(raw[1:], 1):
        for (j, item) in enumerate(line[1:], 1):
            raw[i][j] = int(item)
    
    print("Data after conversion:")
    print(raw)
    
    # 3) Use the data...
    print("Use the data")
    for i in range(1, len(raw)):
      print("Sum for Player %d: %d" %(i, sum(raw[i][1:])) )
    
    for i in range(1, len(raw)):
      print("Total points in Game %d: %d" %(i, sum(list(zip(*raw))[i][1:])) )
    

    输出将是:

    Raw data:
    
           , Game1, Game2,   Game3,   Game4,   Game5
    Player1,  2,    6,       5,       2,     2
    Player2,  6,      4 ,      1,       8,      4
    Player3,  8,     3 ,      2,    1,     5
    Player4,  4,  9 ,   4,     7,    9
    
    Data after Read:
    [['', 'Game1', 'Game2', 'Game3', 'Game4', 'Game5'], ['Player1', '2', '6', '5', '2', '2'], ['Player2', '6', '4', '1', '8', '4'], ['Player3', '8', '3', '2', '1', '5'], ['Player4', '4', '9', '4', '7', '9']]
    Data after conversion:
    [['', 'Game1', 'Game2', 'Game3', 'Game4', 'Game5'], ['Player1', 2, 6, 5, 2, 2], ['Player2', 6, 4, 1, 8, 4], ['Player3', 8, 3, 2, 1, 5], ['Player4', 4, 9, 4, 7, 9]]
    Use the data
    Sum for Player 1: 17
    Sum for Player 2: 23
    Sum for Player 3: 19
    Sum for Player 4: 33
    Total points in Game 1: 20
    Total points in Game 2: 22
    Total points in Game 3: 12
    Total points in Game 4: 18
    

    【讨论】:

    • 我认为它是一个字符串数组。他没有使用任何东西来转换字符串数字,更不用说结构化数组了。
    • 我明白了,每天都在学习新的东西......我只是假设 csv.reader “足够聪明”可以捕获这样的结构化数据(R 的方式)并使用结构化数组。 +1 通知我好先生。
    • 我遇到了这个问题,因为传递的是字符串而不是整数。我认为接受的答案是“使用 Pandas”有点奇怪。int(var) 对我有用。
    【解决方案3】:

    考虑使用Pandas module

    import pandas as pd
    
    df = pd.read_csv('/path/to.file.csv', sep=';')
    

    结果数据框:

    In [196]: df
    Out[196]:
             Game1  Game2  Game3  Game4  Game5
    Player1      2      6      5      2      2
    Player2      6      4      1      8      4
    Player3      8      3      2      1      5
    Player4      4      9      4      7      9
    

    总和:

    In [197]: df.sum(axis=1)
    Out[197]:
    Player1    17
    Player2    23
    Player3    19
    Player4    33
    dtype: int64
    
    In [198]: df.sum(1).values
    Out[198]: array([17, 23, 19, 33], dtype=int64)
    

    【讨论】:

    • 感谢它与此示例完美配合。但是,例如,当我有 for player 118807.51639, 133913.1112, 8731.994713, 16584.42291 and 9315,486864 时,总和为零。请问有什么想法吗?
    【解决方案4】:

    你根本不需要 numpy,只需这样做:

    import csv
    from collections import OrderedDict
    
    with open('games') as f:
        reader = csv.reader(f, delimiter=';')
        data = list(reader)
    
    sums = OrderedDict()
    for row in data[1:]:
        player, games = row[0], row[1:]
        sums[player] = sum(map(int, games))
    

    【讨论】:

      猜你喜欢
      • 2014-02-23
      • 1970-01-01
      • 2016-09-13
      • 2020-10-03
      • 1970-01-01
      • 2013-12-02
      • 2015-09-12
      • 2015-04-08
      • 1970-01-01
      相关资源
      最近更新 更多