我尝试更新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
吗?
答案 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)
我通过删除新列并加入替换DataFrame中的数据来实现这一点:
df1 = df1.drop(columns=df2.columns).join(df2)
这告诉Pandas使用df1
中的值从df2
中删除要重新创建的列。请注意,由于新列被追加到末尾,所以列顺序会发生变化。
遍历替换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]
使用这两种方法,如果您的索引在df1
和df2
之间不匹配,则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