使用NaN值按数据框更新数据框

时间:2018-10-09 20:02:12

标签: python pandas dataframe updates

我尝试更新DataFrame

df1 = pd.DataFrame(data = {'A' : [1,2,3,4], 'B' : [5,6,7,8]})

由另一个DataFrame

df2 = pd.DataFrame(data = {'B' : [9, np.nan, 11, np.nan]}).

现在,我的目标是将df1更新为df2,并使用

覆盖所有值(也覆盖NaN值)
df1.update(df2)

与常用用法相反,对我来说,最终在NaN中获得df1值对我很重要。 但据我所见,更新返回

>>> df1
      A   B
0     1   9
1     2   6
2     3   11
3     4   8

有没有办法

>>> df1
    A    B
0   1    9
1   2    NaN
2   3    11
3   4    NaN

没有手动构建df1吗?

5 个答案:

答案 0 :(得分:1)

我参加聚会很晚,但是最近遇到了同样的问题,即,试图更新数据框而不像熊猫内置update方法那样忽略NaN值。 对于共享相同列名的两个数据框,一种解决方法是将两个数据框连接起来,然后删除重复项,仅保留最后一个条目:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(data = {'A' : [1,2,3,4], 'B' : [5,6,7,8]})
df2 = pd.DataFrame(data = {'A' : [1,2,3,4], 'B' : [9, np.nan, 11, np.nan]})

frames = [df1, df2]
df_concatenated = pd.concat(frames)
df1=df_concatenated.loc[~df_concatenated.index.duplicated(keep='last')]

取决于索引,可能有必要对输出数据帧的索引进行排序:

df1=df1.sort_index()

要解决一个非常具体的示例,其中df2没有A列,可以运行:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(data = {'A' : [1,2,3,4], 'B' : [5,6,7,8]})
df2 = pd.DataFrame(data = {'B' : [9, np.nan, 11, np.nan]})

frames = [df1, df2]
df_concatenated = pd.concat(frames)

df1['B']=df_concatenated.loc[~df_concatenated.index.duplicated(keep='last')]['B']

答案 1 :(得分:0)

它对我也很好。您也许可以使用np.nan而不是'nan'?

答案 2 :(得分:0)

我猜你是说[9, np.nan, 11, np.nan],而不是字符串"nan".

如果没有强制性要求使用update(),请改为使用df1.B = df2.B,以便新的df1.B将包含NaN

DataFrame.update()仅更新非NA值。参见docs

答案 3 :(得分:0)

方法1:删除所有受影响的列

我通过删除新列并加入替换DataFrame中的数据来实现这一点:

df1 = df1.drop(columns=df2.columns).join(df2)

这告诉Pandas使用df1中的值从df2中删除要重新创建的列。请注意,由于新列被追加到末尾,所以列顺序会发生变化。

方法2:保留列顺序

遍历替换DataFrame中的所有列,在删除原始列之后,在目标DataFrame中的原位置插入受影响的列。如果替换的DataFrame包括不在目标DataFrame中的列,它将被附加到末尾。

for col in df2.columns:
    try:
        col_pos = list(df1.columns).index(col)
        df1.drop(columns=[col], inplace=True)
        df1.insert(col_pos, col, df2[col])
    except ValueError:
        df1[col] = df2[col]

注意

使用这两种方法,如果您的索引在df1df2之间不匹配,则df2中缺少的索引将在输出DataFrame中以NaN结尾:

df1 = pd.DataFrame(data = {'B' : [1,2,3,4,5], 'A' : [5,6,7,8,9]})    # Note the additional row
df2 = pd.DataFrame(data = {'B' : [9, np.nan, 11, np.nan]})
df1.update(df2)

输出:

>>> df1
    B     A
0   9.0   5
1   2.0   6
2   11.0  7
3   4.0   8
4   5.0   9

我的版本1:

df1 = pd.DataFrame(data = {'A' : [1,2,3,4,5], 'B' : [5,6,7,8,9]})
df2 = pd.DataFrame(data = {'B' : [9, np.nan, 11, np.nan]})
df1 = df1.drop(columns=df2.columns).join(df2)

输出:

>>> df1

    A   B
0   5   9.0
1   6   NaN
2   7   11.0
3   8   NaN
4   9   NaN

我的版本2:

df1 = pd.DataFrame(data = {'A' : [1,2,3,4,5], 'B' : [5,6,7,8,9]})
df2 = pd.DataFrame(data = {'B' : [9, np.nan, 11, np.nan]})
for col in df2.columns:
    try:
        col_pos = list(df1.columns).index(col)
        df1.drop(columns=[col], inplace=True)
        df1.insert(col_pos, col, df2[col])
    except ValueError:
        df1[col] = df2[col]

输出:

>>> df1

    B     A
0   9.0   5
1   NaN   6
2   11.0  7
3   NaN   8
4   NaN   9

答案 4 :(得分:0)

一个有用的技巧是用'n / a'这样的字符串填充,然后用np.nan替换'n / a',然后将列类型转换回float

df1 = pd.DataFrame(data = {'A' : [1,2,3,4], 'B' : [5,6,7,8]})
df2 = pd.DataFrame(data = {'B' : [9, 'n/a', 11, 'n/a']})
df1.update(df2)
df1['B'] = df1['B'].replace({'n/a':np.nan})
df1['B'] = df1['B'].apply(pd.to_numeric, errors='coerce')

有关类型转换的一些解释:调用replace之后,结果是:

   A     B
0  1   9.0
1  2   NaN
2  3  11.0
3  4   NaN

这看起来可以接受,但实际上B列的类型已从float更改为object。

df1.dtypes

会给予

A     int64
B    object
dtype: object

要将其设置为浮动,可以使用:

df1['B'] = df1['B'].apply(pd.to_numeric, errors='coerce')

然后,您将获得预期的结果:

df1.dtypes

将给出预期的类型:

A      int64
B    float64
dtype: object