【问题标题】:Divide two pandas DataFrames and keep non-numeric columns划分两个 pandas DataFrames 并保留非数字列
【发布时间】:2018-03-22 01:27:40
【问题描述】:

我有两个包含数字和非数字值的 pandas DataFrame。我想一分为二,但保留非数字列。这是一个 MWE:

a = pd.DataFrame(
    [
        ['group1', 1., 2.],
        ['group1', 3., 4.],
        ['group1', 5., 6.]
    ], 
    columns=['Group', 'A', 'B']
)

b = pd.DataFrame(
    [
        ['group1', 7., 8.],
        ['group1', 9., 10.],
        ['group1', 11., 12.]
    ],
    columns=['Group', 'A', 'B']
)

尝试做:

b.div(a)

结果:

TypeError: unsupported operand type(s) for /: 'str' and 'str'

所以为了解决这个问题,我已经完成了:

result = b.drop(["Group"], axis=1).div(a.drop(["Group"], axis=1))
print(result)
#     A    B
#0  7.0  4.0
#1  3.0  2.5
#2  2.2  2.0

这是正确的,但我也想保留专栏"Group"

获得我想要的输出的一种方法是:

desired_output = b[["Group"]].join(result)
print(desired_output)
#    Group    A    B
#0  group1  7.0  4.0
#1  group1  3.0  2.5
#2  group1  2.2  2.0

但我真正的 DataFrame 有许多非数字列。有没有更干净/更快/更有效的方法来告诉 pandas 只划分数字列?

【问题讨论】:

  • @BradSolomon 是的,两者的非数字列是相同的。实际数据来自 2 个不同的时间段。我正在尝试计算百分比变化。

标签: python pandas


【解决方案1】:

您可以使用np.divide,将掩码传递给where 参数。

np.divide(b, a, where=a.dtypes.ne(object))

假设非数字列在 DataFrames 中是相同的,请使用 combine_first/fillna 将它们取回:

np.divide(b, a, where=a.dtypes.ne(object)).combine_first(a)


    Group    A    B
0  group1  7.0  4.0
1  group1  3.0  2.5
2  group1  2.2  2.0

【讨论】:

    【解决方案2】:

    类似于@cᴏʟᴅsᴘᴇᴇᴅ 的回答,但您可以通过.select_dtypes() 留在 Pandas 中。这将尝试对任何非对象 dtype 进行索引对齐除法。

    >>> b.select_dtypes(exclude='object').div(
    ...     a.select_dtypes(exclude='object')).combine_first(a)
    ...     
         A    B   Group
    0  7.0  4.0  group1
    1  3.0  2.5  group1
    2  2.2  2.0  group1
    

    保留列顺序:

    >>> desired_output = b.select_dtypes(exclude='object')\
    ...     .div(a.select_dtypes(exclude='object'))\
    ...     .combine_first(a)[a.columns]
    
    >>> desired_output
        Group    A    B
    0  group1  7.0  4.0
    1  group1  3.0  2.5
    2  group1  2.2  2.0
    

    【讨论】:

      【解决方案3】:

      也许set_index()

      b.set_index('Group').div(a.set_index('Group'),level=[0]).reset_index()
      Out[579]: 
          Group    A    B
      0  group1  7.0  4.0
      1  group1  3.0  2.5
      2  group1  2.2  2.0
      

      处理更多字符串类型的列

      pd.concat([b,a]).groupby(level=0).agg(lambda x : x.iloc[0]/x.iloc[1] if x.dtype=='int64' else x.head(1))
      Out[584]: 
          Group     A     B
      0  group1   7.0   8.0
      1  group1   9.0  10.0
      2  group1  11.0  12.0
      

      【讨论】:

      • 很好,但如果有多个字符串列(您需要全部设置),则无法使用。
      猜你喜欢
      • 2018-01-29
      • 2020-09-04
      • 2018-05-16
      • 2018-10-19
      • 2023-02-22
      • 2021-11-01
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      相关资源
      最近更新 更多