首页 > 技术文章 > df.conbine() \df.conbine_first() \df.update()逐元素合并

Teyisang 2021-04-17 18:23 原文

df.combine_first()

使用相同位置的值更新空元素,它只能是 df1 有空元素时才能被替换,如果数据结构不一致,所得 DataFrame的行索引和列索引将是两者的并集。

df1 = pd.DataFrame({'A': [None, 0], 'B': [None, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
df1.combine_first(df2)
'''
     A    B
0  1.0  3.0
1  0.0  4.0
'''

在上例中,df1 中的 A 和 B 的空值被 df2 中的相同位置值替换。

df1 = pd.DataFrame({'A': [None, 0], 'B': [4, None]})
df2 = pd.DataFrame({'B': [3, 3], 'C': [1, 1]}, index=[1, 2])
df1.combine_first(df2)
'''
     A      B     C
0  NaN  4.0  NaN
1  0.0    3.0  1.0
2  NaN  3.0  1.0
'''

在上例中,df1 中的 A 中的空值由于没有相同位置值来替换,仍然为空。

df. combine()

可以与另一个 DataFrame 进行按列组合。使用函数将一个 DataFrame 与其他DataFrame合并,以逐元素合并列。 所得 DataFrame 的行索引和列索引将是两者的并集。

这个函数中有两个参数,分别是两个 df 中对应的 series, 计算后返回一个 Series 或者标量。

df1 = pd.DataFrame({'A': [0, 0], 'B': [4, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
# s1 列总和如果小于 s2列总和取 s1, 否则取 s2
take_smaller = lambda s1, s2: s1 if s1.sum() < s2.sum() else s2
df1.combine(df2, take_smaller)
'''
    A  B
0  0  3
1  0  3
'''

也可以直接使用 numpy 的函数:

df1 = pd.DataFrame({'A': [5, 0], 'B': [2, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
# 每个对应元素中最小的
df1.combine(df2, np.minimum)
    A  B
0  1  2
1  0  3

对于空值缺失值可以指定填充值,填充完后代入计算:

df1 = pd.DataFrame({'A': [0, 0], 'B': [None, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
df1.combine(df2, take_smaller, fill_value=-5)
'''
    A    B
0  0   -5.0
1  0   4.0
''

但是,如果两个数据帧中的相同元素均为“无”,则将保留“无”:

df1 = pd.DataFrame({'A': [0, 0], 'B': [None, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [None, 3]})
df1.combine(df2, take_smaller, fill_value=-5)
'''
    A    B
0  0  -5.0
1  0   3.0
'''

以下是轴不同时合并覆盖和行为,均会为空值。

df1 = pd.DataFrame({'A': [0, 0], 'B': [4, 4]})
df2 = pd.DataFrame({'B': [3, 3], 'C': [-10, 1], }, index=[1, 2])
df1.combine(df2, take_smaller)
'''
       A      B      C
0  NaN  NaN   NaN
1  NaN  3.0     -10.0
2  NaN  3.0     1.0
'''
# overwrite 不存在的列将不被NaN覆盖
df1.combine(df2, take_smaller, overwrite=False)
'''
      A        B     C
0  0.0    NaN   NaN
1  0.0    3.0     -10.0
2  NaN  3.0     1.0
'''

以下是不同行索引的示例:

df2 = pd.DataFrame({'B': [3, 3], 'C': [1, 1], }, index=[1, 2])
df2.combine(df1, take_smaller)
   A    B   C
0  0.0  NaN NaN
1  0.0  3.0 NaN
2  NaN  3.0 NaN

df2.combine(df1, take_smaller, overwrite=False)
     A         B       C
0  0.0    NaN    NaN
1  0.0    3.0      1.0
2  NaN  3.0      1.0

df.update()

使用来自另一个 DataFrame 的非NA值进行修改,原 df 为被更新。

df = pd.DataFrame({'A': [1, 2, 3],
                   'B': [400, 500, 600]})
new_df = pd.DataFrame({'B': [4, 5, 6],
                       'C': [7, 8, 9]})
df.update(new_df)
df
    A  B
0  1  4
1  2  5
2  3  6

DataFrame的长度不会增加,只会更新匹配的索引/列标签上的值。

df = pd.DataFrame({'A': ['a', 'b', 'c'],
                   'B': ['x', 'y', 'z']})
new_df = pd.DataFrame({'B': ['d', 'e', 'f', 'g', 'h', 'i']})
df.update(new_df)
df
  A  B
0  a  d
1  b  e
2  c  f

对于系列,必须设置其名称属性。

df = pd.DataFrame({'A': ['a', 'b', 'c'],
                   'B': ['x', 'y', 'z']})
new_column = pd.Series(['d', 'e'], name='B', index=[0, 2])
df.update(new_column)
df
  A  B
0  a  d
1  b  y
2  c  e


df = pd.DataFrame({'A': ['a', 'b', 'c'],
                   'B': ['x', 'y', 'z']})
new_df = pd.DataFrame({'B': ['d', 'e']}, index=[1, 2])
df.update(new_df)
df
    A  B
0  a  x
1  b  d
2  c  e

如果其他包含NaN,则相应的值不会在原始数据帧中更新。

df = pd.DataFrame({'A': [1, 2, 3],
                   'B': [400, 500, 600]})
new_df = pd.DataFrame({'B': [4, np.nan, 6]})
df.update(new_df)
df
    A      B
0  1    4.0
1  2    500.0
2  3    6.0

推荐阅读