考虑以下带有两个类别列的DataFrame:
df = pd.DataFrame({
"state": pd.Categorical(["AK", "AL", "AK", "AL"]),
"gender": pd.Categorical(["M", "M", "M", "F"]),
"name": list("abcd"),
})
在df.groupby()
中,默认值为observed=False
。 observed
(Pandas 0.25.0)的description为:
在使用分类石斑鱼(作为单个石斑鱼,或作为多个石斑鱼的一部分)时,observed关键字控制是否返回所有可能的石斑鱼值的笛卡尔积(observed = False)还是仅那些被观察到的石斑鱼(observed = True)。
因此,这是我期望的结果:
>>> # Expected result
>>> df.groupby(["state", "gender"])["name"].count()
state gender
AK M 2
F 0
AL F 1
M 1
Name: name, dtype: int64
这是实际结果:
>>> df.groupby(["state", "gender"])["name"].count()
state gender
AK M 2
AL F 1
M 1
Name: name, dtype: int64
我在这里误解了描述吗?
此解决方法似乎是一个巨大的痛苦,而observed=False
正是应该创建的。我是否缺少其他选择?
>>> idx = pd.MultiIndex.from_product(
... (
... df["state"].cat.categories,
... df["gender"].cat.categories,
... ),
... names=["state", "gender"]
... )
>>> df.groupby(["state", "gender"])["name"].count().reindex(idx).fillna(0.).astype(int)
state gender
AK F 0
M 2
AL F 1
M 1
Name: name, dtype: int64
答案 0 :(得分:3)
似乎您放置["name"]
的位置正在扔掉它。我认为这可行:
df.groupby(["state", "gender"]).count().fillna(0)["name"]
state gender
AK F 0.0
M 2.0
AL F 1.0
M 1.0
Name: name, dtype: float64
以下是一些有用的变体:
In [16]: df.groupby(["state", "gender"], observed=False).count().fillna(0)["name"].astype(int)
Out[16]:
state gender
AK F 0
M 2
AL F 1
M 1
Name: name, dtype: int64
In [17]: df.groupby(["state", "gender"], observed=True).count()["name"]
Out[17]:
state gender
AK M 2
AL M 1
F 1
Name: name, dtype: int64
答案 1 :(得分:1)
我同样不确定observed
。但是,您想要的结果并不难得到。跟踪.unstack(fill_value=0).stack()
。
>>> import pandas as pd
>>> df = pd.DataFrame({
... "state": pd.Categorical(["AK", "AL", "AK", "AL"]),
... "gender": pd.Categorical(["M", "M", "M", "F"]),
... "name": list("abcd"),
... })
>>> df.groupby(['state', 'gender'])['name'].count().unstack(fill_value=0).stack()
state gender
AK M 2
F 0
AL M 1
F 1
dtype: int64
答案 2 :(得分:1)
使用crosstab
pd.crosstab(df.state,df.gender).stack()
state gender
AK F 0
M 2
AL F 1
M 1
dtype: int64