我发现自己必须经常做一件事,令我惊讶的是,在熊猫中实现这一目标是多么困难。假设我需要创建一个具有指定索引类型和名称以及列类型和名称的空DataFrame
。 (我可能希望稍后在循环中填充它。例如。)我发现,最简单的方法是为每列创建一个空的pandas.Series
对象,指定它们dtype
s,将它们放入指定其名称的字典中,并将字典传递给DataFrame
构造函数。如下所示。
def create_empty_dataframe():
index = pandas.Index([], name="id", dtype=int)
column_names = ["name", "score", "height", "weight"]
series = [pandas.Series(dtype=str), pandas.Series(dtype=int), pandas.Series(dtype=float), pandas.Series(dtype=float)]
columns = dict(zip(column_names, series))
return pandas.DataFrame(columns, index=index, columns=column_names)
# The columns=column_names is required because the dictionary will in general put the columns in arbitrary order.
第一个问题。上面真的是最简单的方法吗?关于这一点有很多令人费解的事情。我真正想做的事情,以及我很确定很多人真正想做的事情,就像下面这样。
df = pandas.DataFrame(columns=["id", "name", "score", "height", "weight"], dtypes=[int, str, int, float, float], index_column="id")
第二个问题。在熊猫中这种语法是否可行?如果不是,开发人员是否考虑支持这样的事情?我觉得它真的应该像这样简单(上面的语法)。
答案 0 :(得分:3)
不幸的是,DateFrame
ctor接受了一个dtype
描述符,但您可以使用read_csv
作弊:
In [143]:
import pandas as pd
import io
cols=["id", "name", "score", "height", "weight"]
df = pd.read_csv(io.StringIO(""), names=cols, dtype=dict(zip(cols,[int, str, int, float, float])), index_col=['id'])
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 0 entries
Data columns (total 4 columns):
name 0 non-null object
score 0 non-null int32
height 0 non-null float64
weight 0 non-null float64
dtypes: float64(2), int32(1), object(1)
memory usage: 0.0+ bytes
因此,您可以看到dtypes符合要求,并且索引是根据需要设置的:
In [145]:
df.index
Out[145]:
Int64Index([], dtype='int64', name='id')
答案 1 :(得分:2)
您也可以通过替换它来设置DataFrame列的dtype:
static void set_refspecs(const char **refs, int nr)
{
int i;
for (i = 0; i < nr; i++) {
const char *ref = refs[i];
if (!strcmp("tag", ref)) {
char *tag;
int len;
if (nr <= ++i)
die("tag shorthand without <tag>");
len = strlen(refs[i]) + 11;
if (deleterefs) {
tag = xmalloc(len+1);
strcpy(tag, ":refs/tags/");
} else {
tag = xmalloc(len);
strcpy(tag, "refs/tags/");
}
strcat(tag, refs[i]);
ref = tag;
} else if (deleterefs && !strchr(ref, ':')) {
char *delref;
int len = strlen(ref)+1;
delref = xmalloc(len+1);
strcpy(delref, ":");
strcat(delref, ref);
ref = delref;
} else if (deleterefs)
die("--delete only accepts plain target ref names");
add_refspec(ref);
}
}
答案 2 :(得分:1)
使用列表理解
可以简化一些事情def create_empty_dataframe():
index = pandas.Index([], name="id", dtype=int)
# specify column name and data type
columns = [('name', str),
('score', int),
('height', float),
('weight', float)]
# create the dataframe from a dict
return pandas.DataFrame({k: pandas.Series(dtype=t) for k, t in columns})
这与你已经完成的工作没有太大的不同,但是在不必修改代码中的多个位置的情况下制作任意数据帧应该更容易。
答案 3 :(得分:0)
这是一个基于@ Elliot答案的通用函数:
import pandas as pd
def create_empty_DataFrame(columns, index_col):
index_type = next((t for name, t in columns if name == index_col))
df = pd.DataFrame({name: pd.Series(dtype=t) for name, t in columns if name != index_col},
index=pd.Index([], dtype=index_type))
cols = [name for name, _ in columns]
cols.remove(index_col)
return df[cols]
请注意,保留非索引列的顺序需要return df[cols]
而不是return df
。一些测试代码:
columns = [
('id', str),
('primary', bool),
('side', str),
('quantity', int),
('price', float)]
table = create_empty_DataFrame(columns, 'id')
检查dtypes
和索引:
table.info()
<class 'pandas.core.frame.DataFrame'>
Index: 0 entries
Data columns (total 4 columns):
primary 0 non-null bool
side 0 non-null object
quantity 0 non-null int64
price 0 non-null float64
dtypes: bool(1), float64(1), int64(1), object(1)
memory usage: 0.0+ bytes
table.index
Index([], dtype='object', name='id')
答案 4 :(得分:0)
import pandas as pd
df = pd.DataFrame([{'col00':int(0),'col01':float(0),'col02':str('xx')}])
df = pd.DataFrame([], None, df.columns)
print df