将行插入 pandas DataFrame,同时维护列数据类型

gro*_*uck 5 python append dataframe pandas

将新行插入现有 pandas DataFrame 同时维护列数据类型并同时为未指定的列提供用户定义的填充值的最佳方法是什么?这是一个例子:

df = pd.DataFrame({
    'name': ['Bob', 'Sue', 'Tom'],
    'age': [45, 40, 10],
    'weight': [143.2, 130.2, 34.9],
    'has_children': [True, True, False]
})
Run Code Online (Sandbox Code Playgroud)

假设我想添加一条新记录,仅传递nameage。为了维护数据类型,我可以从 复制行df,修改值,然后附加df到副本,例如

columns = ('name', 'age')
copy_df = df.loc[0:0, columns].copy()
copy_df.loc[0, columns] = 'Cindy', 42
new_df = copy_df.append(df, sort=False).reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)

但这会将bool列转换为对象。

这是一个非常棘手的解决方案,感觉不是执行此操作的“正确方法”:

columns = ('name', 'age')
copy_df = df.loc[0:0].copy()

missing_remap = {
    'int64': 0,
    'float64': 0.0,
    'bool': False,
    'object': ''
}
for c in set(copy_df.columns).difference(columns)):
    copy_df.loc[:, c] = missing_remap[str(copy_df[c].dtype)]

new_df = copy_df.append(df, sort=False).reset_index(drop=True)
new_df.loc[0, columns] = 'Cindy', 42
Run Code Online (Sandbox Code Playgroud)

我知道我一定错过了什么。

jpp*_*jpp 4

正如您所发现的,由于NaN是 a float,因此添加NaN到系列可能会导致它向上转换为float或转换为object。您确定这不是理想的结果是正确的。

没有直接的方法。我的建议是将输入行数据存储在字典中,并在附加之前将其与默认字典结合起来。请注意,这是有效的,因为pd.DataFrame.append它接受一个dict参数。

在 Python 3.6 中,您可以使用语法{**d1, **d2}来组合两个字典,并优先选择第二个字典。

default = {'name': '', 'age': 0, 'weight': 0.0, 'has_children': False}

row = {'name': 'Cindy', 'age': 42}

df = df.append({**default, **row}, ignore_index=True)

print(df)

   age  has_children   name  weight
0   45          True    Bob   143.2
1   40          True    Sue   130.2
2   10         False    Tom    34.9
3   42         False  Cindy     0.0

print(df.dtypes)

age               int64
has_children       bool
name             object
weight          float64
dtype: object
Run Code Online (Sandbox Code Playgroud)