【问题标题】:How to prevent Pandas from converting my integers to floats when I merge two dataFrames?当我合并两个数据帧时,如何防止 Pandas 将我的整数转换为浮点数?
【发布时间】:2016-11-21 12:27:36
【问题描述】:

这是我的代码:

import pandas as pd
left = pd.DataFrame({'AID': [1, 2, 3, 4],
                       'D': [2011, 2011,0, 2011],
                       'R1': [0, 1, 0, 0],
                       'R2': [1, 0, 0, 0]  })

right = pd.DataFrame({'AID': [1, 2, 3, 4],
                       'D': [2012, 0,0, 2012],
                       'R1': [0, 1, 0, 0],
                       'R2': [1, 0, 0, 0]  })

result = left.merge(right, how = 'outer')

当我打印我的结果数据帧时,整数值现在是浮点数:

   AID       D   R1   R2
0  1.0  2011.0  0.0  1.0
1  2.0  2011.0  1.0  0.0
2  3.0     0.0  0.0  0.0
3  4.0  2011.0  0.0  0.0
4  1.0  2012.0  0.0  1.0
5  2.0     0.0  1.0  0.0
6  4.0  2012.0  0.0  0.0

如何防止这种情况发生?

【问题讨论】:

  • 显然这是一个错误,将在 0.18.2 中修复 github.com/pydata/pandas/issues/8596
  • 我可以重现此问题并已投票重新打开。重现所需的代码略有不同
  • left = pd.DataFrame({'AID': [1, 2, 3, 4], 'D': [2011, 2011,0, 2011], 'R1': [0, 1, 0, 0], }) 右 = pd.DataFrame({'AID': [1, 2, 3, 4], 'D': [2012, 0,0, 2012], 'R2': [1 , 0, 0, 0] }) 结果 = left.merge(right, how = 'outer', on=['AID', 'D']) 结果
  • 请注意,如果由于两个数据帧的索引或列之间的不匹配而产生 NaN 值,则浮点数可能会出现在人们只期望整数的地方。请注意如何指定合并类型,即如何在.merge() 中设置how kwarg。这是我问题的根源。最后,我尝试了 Rakesh 的代码,但无法重现他/她的错误。

标签: python pandas


【解决方案1】:

此错误已在 pandas v0.19.0. 中修复:

合并现在将保留连接键的数据类型

但请注意,您可以使用以下方法将数据框中的所有列转换为 int dtype:

result = result.astype(int)

如果连接中有不匹配的记录,则此行为does still occur,因此结果中的NaNs。在这种情况下,您需要将dtype更改为extension type'Int64'来处理NaNs:

result = result.astype('Int64')

【讨论】:

    【解决方案2】:

    您可以将浮点数转换回 using

     result = left.merge(right, on='AID', how = 'outer')
    
     result['D_x']=result['D_x'].astype('Int64')
     result['R1_x']=result['R1_x'].astype('Int64')
     result['R2_x']=result['R2_x'].astype('Int64')
     result['D_y']=result['D_y'].astype('Int64')
     result['R1_y']=result['R1_y'].astype('Int64')
     result['R2_y']=result['R2_y'].astype('Int64')
    

    如果数据有空或缺失数据

    import numbers
    import math
    
    left = pd.DataFrame({'AID': [1, 2, 3, 4],
                       'D': [2011, 2011,0, 2011],
                       'R1': [0, 1, 0, 0],
                       'R2': [1, 0, 0, 0]  })
    
    right = pd.DataFrame({'AID': [1, 2, 3, 4],
                       'D': [2012, 0,0, 2012],
                       'R1': [0, 1, 0, 0],
                       'R2': [1, 0, 0, 0]  })
    
    result = left.merge(right, how = 'outer')
    result['AID']=[int(val) if isinstance(val,numbers.Number) & (math.isnan(val)==False) else 0 for val in result['AID']]
    result['D']=[int(val) if isinstance(val,numbers.Number) & (math.isnan(val)==False) else 0 for val in result['D']]
    result['R1']=[int(val) if isinstance(val,numbers.Number) & (math.isnan(val)==False) else 0 for val in result['R1']]
    result['R2']=[int(val) if isinstance(val,numbers.Number) & (math.isnan(val)==False) else 0 for val in result['R2']]
    
     print(result)
     print(result.isna())
    

    输出

    AID     D  R1  R2
    0    1  2011   0   1
    1    2  2011   1   0
    2    3     0   0   0
    3    4  2011   0   0
    4    1  2012   0   1
    5    2     0   1   0
    6    4  2012   0   0
    
       AID      D     R1     R2
    0  False  False  False  False
    1  False  False  False  False
    2  False  False  False  False
    3  False  False  False  False
    4  False  False  False  False
    5  False  False  False  False
    6  False  False  False  False    
    

    然后,您可以将 nan 值替换为:均值、0 或插值

    固定 D 列

    def interpolate_list(y):
        idx = np.nonzero(y)
        x = np.arange(len(y))
        interp = interp1d(x[idx],y[idx])
       new_values = interp(x)
       return new_values
    
    interp_d=interpolate_list(np.array(result['D']))
    data=list(zip(interp_d,result['D']))
    result['D']=[item[0] if item[1]==0 else item[1] for item in data]
    print(result)
    

    输出

       AID       D  R1  R2
    0    1  2011.0   0   1
    1    2  2011.0   1   0
    2    3  2011.0   0   0
    3    4  2011.0   0   0
    4    1  2012.0   0   1
    5    2  2012.0   1   0
    6    4  2012.0   0   0
    

    【讨论】:

    • 这行得通,除非有不匹配的记录(如另一个响应中提到的),其中某些字段包含NaN。在这种情况下,您需要.astype('Int64')
    【解决方案3】:

    我遇到了同样的问题,这是因为合并后我在重铸列中得到了一些 NaN 值。

    所以,我的“之前”列是 int32,而“现在”表是 float64。

    当我想将它重铸为 int32 时,我遇到了这个问题:

    “ValueError:无法将非有限值(NA 或 inf)转换为整数”

    所以我把它留在 float64 上:D

    【讨论】:

      猜你喜欢
      • 2014-06-14
      • 2018-05-03
      • 2020-01-28
      • 2017-06-11
      • 2021-10-16
      • 1970-01-01
      • 2014-02-13
      相关资源
      最近更新 更多