如何舍入包含混合数据类型的 Pandas DataFrame 中的值以进行进一步的数据比较?

toa*_*eez 5 python numpy pandas

我有一个数据框 df_left:

  IDX1 IDX2 IDX3     IDX4 ValueType Value
0    A   A1    Q  1983 Q4         W    10.123
1    A   A1    Q  1983 Q4         X     A
2    A   A1    Q  1983 Q4         Y     F
3    A   A1    Q  1983 Q4         Z   NaN
4    A   A1    Q  1984 Q1         W   110.456
...
Run Code Online (Sandbox Code Playgroud)

从以前的帖子创建:

背景资料

AND 数据框 df_right:

  IDX1 IDX2 IDX3     IDX4 ValueType Value
0    A   A1    Q  1983 Q4         W    10
1    A   A1    Q  1983 Q4         X     A
2    A   A1    Q  1983 Q4         Y     F
3    A   A1    Q  1983 Q4         Z   NaN
4    A   A1    Q  1984 Q1         W   110
Run Code Online (Sandbox Code Playgroud)

我比较并协调以下数据的值和文本:

df_compare = pd.merge(df_Left, df_Right, how ='outer', on = ['IDX1', 'IDX2', 'IDX3', 'IDX4', 'ValueType'])
df_compare.columns = ['IDX1', 'IDX2', 'IDX3', 'IDX4', 'ValueType', 'From', 'To']
df_compare = df_compare[df_compare.From!=df_compare.To]
Run Code Online (Sandbox Code Playgroud)

虽然结果如预期,但在比较之前,我想对值 coulmn 中的数据进行四舍五入。

我试过了:

df.apply(np.round)
Run Code Online (Sandbox Code Playgroud)

并且:

df.round(decimals=0, out=None)
Run Code Online (Sandbox Code Playgroud)

但都如预期的那样出现错误:

AttributeError: ("'str' object has no attribute 'rint'", u'occurred at index Code')

Joh*_*hnE 5

这是一个可以应用于多列的相当通用的解决方案。'To' 列不需要四舍五入,我只是为了两列而不是一列的一般性而包含它:

df

  IDX1 IDX2  IDX3 IDX4 ValueType     From   To
0   A1    Q  1983   Q4         W   10.123   10
3   A1    Q  1983   Q4         Z      NaN  NaN
4   A1    Q  1984   Q1         W  110.456  110

In [399]: df[['From','To']].astype(float).apply(np.round)

   From   To
0    10   10
3   NaN  NaN
4   110  110
Run Code Online (Sandbox Code Playgroud)

这是最安全的方法,因为它不会让您意外删除非数字值,但如果您真的有混合类型,您可以这样做:

df[['From','To']].convert_objects(convert_numeric=True).apply(np.round)

   From   To
0    10   10
3   NaN  NaN
4   110  110
Run Code Online (Sandbox Code Playgroud)

但由于这会将任何非数字值转换为 NaN,因此在覆盖任何内容之前,请确保这是您想要的。


UNa*_*amy 1

仅对浮点数进行舍入的自定义方法可以解决对混合数据类型列进行舍入的问题


In [238]: def round_float(s):
    '''1. if s is float, round it to 0 decimals
       2. else return s as is
    '''
    import re
    m = re.match("(\d+\.\d+)",s.__str__())
    try:
        r = round(float(m.groups(0)[0]),0)
    except:
        r = s
    return r

In [239]: s = u'''  IDX1 IDX2 IDX3     IDX4 ValueType Value
0    A   A1    Q  1983 Q4         W    10.23
1    A   A1    Q  1983 Q4         X     A
2    A   A1    Q  1983 Q4         Y     F
3    A   A1    Q  1983 Q4         Z   NaN
4    A   A1    Q  1984 Q1         W   110.15'''

In [240]: df1 = pd.read_csv(StringIO(s), delimiter="\s+")

In [241]: df1["Value2"] = df1.Value.apply(round_float)

In [242]: df1
Out[242]:
    IDX1 IDX2  IDX3 IDX4 ValueType   Value Value2
0 A   A1    Q  1983   Q4         W   10.23     10
1 A   A1    Q  1983   Q4         X       A      A
2 A   A1    Q  1983   Q4         Y       F      F
3 A   A1    Q  1983   Q4         Z     NaN    NaN
4 A   A1    Q  1984   Q1         W  110.15    110
Run Code Online (Sandbox Code Playgroud)