【问题标题】:Handling HUGE numbers in numpy or pandas在 numpy 或 pandas 中处理巨大的数字
【发布时间】:2014-03-02 16:51:04
【问题描述】:

我正在参加一项竞赛,向我提供匿名数据。相当多的列具有巨大的价值。最大的是40位数长!我使用了pd.read_csv,但结果这些列已转换为对象。

我最初的计划是按比例缩小数据,但由于它们被视为对象,我无法对它们进行算术运算。

有人对如何在 Pandas 或 Numpy 中处理大量数字有任何建议吗?

请注意,我尝试将值转换为 uint64,但没有成功。我收到错误“long too big to convert”

【问题讨论】:

  • 这 40 位数值真的是数字数据,还是 ID 字符串?
  • 巨大的值是整数还是浮点数?
  • @Marius 显然它们是数字数据。比赛的论坛也有同样的问题,但主持人说要按数字处理。 dawg 巨大的值是整数
  • 我不确定是什么问题。如果对象是大整数,您可以对 dtype=object 列进行算术运算。
  • @DSM 看起来有些长数字被视为字符串,因此不允许算术

标签: python numpy pandas


【解决方案1】:

编辑:这些也不能(准确地)表示为浮点数,当您尝试时它不会引发......可能最好使用 object dtype 和 longs 作为 DSM 的答案。

但你可能做的不准确(使用@DSM的例子):

In [11]: df = pd.DataFrame({"A": [11**44, "11"*22]}).astype(float)

In [12]: df
Out[12]: 
              A
0  6.626408e+45
1  1.111111e+43

[2 rows x 1 columns]

In [13]: df.dtypes
Out[13]: 
A    float64
dtype: object

但这可能不是你想要的......

In [21]: df.iloc[0, 0]
Out[21]: 6.6264076077366411e+45

In [22]: long(df.iloc[0, 0])
Out[22]: 6626407607736641089115845702792172379125579776L

In [23]: 11 ** 44
Out[23]: 6626407607736641103900260617069258125403649041L

正如 DSM 建议的那样,转换为 long(并使用 object dtype)以免失去准确性:

In [31]: df = pd.DataFrame({"A": [11**44, "11"*22]}).apply(long, 1)

In [32]: df
Out[32]: 
0    6626407607736641103900260617069258125403649041
1      11111111111111111111111111111111111111111111
dtype: object

【讨论】:

  • 哇,我很震惊我们可以将它更改为浮动并让它工作......我接受你的答案,因为你的答案是最简单的,并且使用科学记数法使事情更容易阅读。谢谢!
  • 当然你知道一个40位的整数字符串不能完全用浮点数表示,对吧?
  • @dawg 感谢您注意到这一点。我接受了 DSM 的回答,因为这样可以保持准确性
【解决方案2】:

您可以在导入字符串时使用 Pandas converters 调用 int 或其他一些自定义转换器函数:

import pandas as pd 
from StringIO import StringIO

txt='''\
line,Big_Num,text
1,1234567890123456789012345678901234567890,"That sure is a big number"
2,9999999999999999999999999999999999999999,"That is an even BIGGER number"
3,1,"Tiny"
4,-9999999999999999999999999999999999999999,"Really negative"
'''

df=pd.read_csv(StringIO(txt), converters={'Big_Num':int})

print df

打印:

   line                                    Big_Num                           text
0     1   1234567890123456789012345678901234567890      That sure is a big number
1     2   9999999999999999999999999999999999999999  That is an even BIGGER number
2     3                                          1                           Tiny
3     4  -9999999999999999999999999999999999999999                Really negative

现在测试算术:

n=df["Big_Num"][1]
print n,n+1 

打印:

9999999999999999999999999999999999999999 10000000000000000000000000000000000000000

如果您的列中有任何值可能导致int 发牢骚,您可以这样做:

txt='''\
line,Big_Num,text
1,1234567890123456789012345678901234567890,"That sure is a big number"
2,9999999999999999999999999999999999999999,"That is an even BIGGER number"
3,0.000000000000000001,"Tiny"
4,"a string","Use 0 for strings"
'''

def conv(s):
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            return 0        

df=pd.read_csv(StringIO(txt), converters={'Big_Num':conv})
print df

打印:

   line                                   Big_Num                           text
0     1  1234567890123456789012345678901234567890      That sure is a big number
1     2  9999999999999999999999999999999999999999  That is an even BIGGER number
2     3                                     1e-18                           Tiny
3     4                                         0              Use 0 for strings

然后列中的每个值都将是 Python int 或 float 并且将支持算术。

【讨论】:

  • 经过一番思考,我决定接受你的回答。 DSM 的答案是准确的,但您的答案既准确又让我能够处理 NaN。谢谢!
【解决方案3】:

如果您有一个混合类型的列 - 一些整数,一些字符串 - 存储在 dtype=object 列中,您仍然可以转换为整数并执行算术运算。从混合类型的列开始:

>>> df = pd.DataFrame({"A": [11**44, "11"*22]})
>>> df
                                                A
0  6626407607736641103900260617069258125403649041
1    11111111111111111111111111111111111111111111

[2 rows x 1 columns]
>>> df.dtypes, list(map(type, df.A))
(A    object
dtype: object, [<type 'long'>, <type 'str'>])

我们可以转换成整数:

>>> df["A"] = df["A"].apply(int)
>>> df.dtypes, list(map(type, df.A))
(A    object
dtype: object, [<type 'long'>, <type 'long'>])
>>> df
                                                A
0  6626407607736641103900260617069258125403649041
1    11111111111111111111111111111111111111111111

[2 rows x 1 columns]

然后进行算术运算:

>>> df // 11
                                               A
0  602400691612421918536387328824478011400331731
1    1010101010101010101010101010101010101010101

[2 rows x 1 columns]

【讨论】:

  • @DSM 谢谢我今晚回家后会查看这个答案
  • Ach 没有。似乎不再如图所示工作。 apply(int) 传递 dtype 对象?
  • 关于。 pandas.to_numeric:“由于 ndarray 的内部限制……可能会发生精度损失……如果传入的数字真的很大……大于 18446744073709551615 的数字”。当与 int 一起应用时,我自己的数字比这个长的会产生对象。 (pandas.pydata.org/pandas-docs/stable/reference/api/…)
猜你喜欢
  • 1970-01-01
  • 2019-03-13
  • 2011-08-31
  • 2010-10-31
  • 2011-05-26
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 2015-12-10
相关资源
最近更新 更多