python - 基于模板在 PYTHON 中更改具有匹配列名的 pandas 数据框列的数据类型
问题描述
我有 2 个数据框。
- 模板 - 我将使用此数据框中的数据类型。
- df - 我想根据模板更改此数据框的数据类型。
我想根据第一个更改第二个数据帧的数据类型。假设我有以下数据框,我将其用作模板。
> template
id <- c(1,2,3,4)
a <- c(1,4,5,6)
b <- as.character(c(0,1,1,4))
c <- as.character(c(0,1,1,0))
d <- c(0,1,1,0)
template <- data.frame(id,a,b,c,d, stringsAsFactors = FALSE)
> str(template)
'data.frame': 4 obs. of 5 variables:
$ id: num 1 2 3 4
$ a : num 1 4 5 6
$ b : chr "0" "1" "1" "4"
$ c : chr "0" "1" "1" "0"
$ d : num 0 1 1 0
我正在寻找下面的东西。
- 将模板的数据类型转换为在 df 中完全相同。
- 它应该具有与模板框架中相同的列。
**注意 - 如果 df 中不可用,它应该添加带有所有 NA 的附加列。
> df
id <- c(6,7,12,14,1,3,4,4)
a <- c(0,1,13,1,3,4,5,6)
b <- c(1,4,12,3,4,5,6,7)
c <- c(0,0,13,3,4,45,6,7)
e <- c(0,0,13,3,4,45,6,7)
df <- data.frame(id,a,b,c,e)
> str(df)
'data.frame': 8 obs. of 5 variables:
$ id: num 6 7 12 14 1 3 4 4
$ a : num 0 1 13 1 3 4 5 6
$ b : num 1 4 12 3 4 5 6 7
$ c : num 0 0 13 3 4 45 6 7
$ e : num 0 0 13 3 4 45 6 7
所需的输出 -
> output
id a b c d
1 6 0 1 0 NA
2 7 1 4 0 NA
3 12 13 12 13 NA
4 14 1 3 3 NA
5 1 3 4 4 NA
6 3 4 5 45 NA
7 4 5 6 6 NA
8 4 6 7 7 NA
> str(output)
'data.frame': 8 obs. of 5 variables:
$ id: num 6 7 12 14 1 3 4 4
$ a : num 0 1 13 1 3 4 5 6
$ b : chr "1" "4" "12" "3" ...
$ c : chr "0" "0" "13" "3" ...
$ d : logi NA NA NA NA NA NA ...
@Frank 的 R 解决方案。
res = data.frame(
lapply(setNames(,names(template)), function(x)
if (x %in% names(df)) as(df[[x]], class(template[[x]]))
else template[[x]][NA_integer_]
), stringsAsFactors = FALSE)
注意-我正在尝试在 Python 中做同样的事情。我是 python 新手,不知道如何处理。任何帮助将不胜感激。
解决方案
在一般情况下,您的问题无法解决,因为熊猫(numpy)中没有integer NaN
和没有booleane NaN
。NaN
应该提升存储数据类型https://pandas.pydata.org/pandas-docs/stable/gotchas.html#support-for-integer-na。你可以这样做:
import numpy as np
import pandas as pd
TEMPLATE = pd.DataFrame(
{'id': pd.Series(dtype=int),
'a': pd.Series(dtype=int),
'b': pd.Series(dtype=str),
'c': pd.Series(dtype=str),
'd': pd.Series(dtype=bool)})
def modify_with_template(df, template):
# type promotion
df_dtypes = df.dtypes.to_dict()
t_dtypes = template.dtypes.to_dict()
to_promote_int = {
col: np.float_
for col in set(t_dtypes.keys()).difference(df_dtypes.keys())
if issubclass(t_dtypes[col].type, np.integer)}
to_promote_bool = {
col: np.object_
for col in set(t_dtypes.keys()).difference(df_dtypes.keys())
if t_dtypes[col].type is np.bool_}
t_dtypes.update(to_promote_int)
t_dtypes.update(to_promote_bool)
# actual modifying
return df.reindex(template.columns, axis=1).astype(t_dtypes)
df = pd.DataFrame({'id': ['1', '0', '1']})
print(df)
df = modify_with_template(df, TEMPLATE)
print(df)
输出:
id
0 1
1 0
2 1
a b c d id
0 NaN NaN NaN NaN 1
1 NaN NaN NaN NaN 0
2 NaN NaN NaN NaN 1
推荐阅读
- linux - bash shell 自动创建用户 - adduser
- vba - VBA - 以矩形复制第一行文本
- kotlin - 不能使用提供的参数调用以下函数 kotlin 错误
- kubernetes - 无法从外部访问 Kubernetes 仪表板
- spring - 使用 swagger-codegen-cli-2.3.1 生成 Spring Boot api 时,是否有任何用于添加日志记录或异常处理的小胡子模板?
- elasticsearch-5 - 如何在冻结的地图中搜索 elassandra?
- scala - 覆盖镶木地板文件会在火花中引发异常
- javascript - 如何在 ReactOpenSeadragon 中添加多个图块图像
- reactjs - SCRIPT438:对象不支持属性或方法“分配”
- css - 是否可以从开发工具直接写入 sass 部分?