如何在pandas多级索引数据框中仅选择索引列?

5

好的,我有一个带有两列索引的DataFrame,我正在尝试过滤掉该DataFrame中的行,并将原始DataFrame的INDEX COLUMNS保留到新的过滤DataFrame中。

我通过以下方式从CSV文件创建了数据框:在此处查找CSV文件

census_df = pd.read_csv("census.csv", index_col = ["STNAME", "CTYNAME"])
census_df.sort_index(ascending = True)

然后,我对DataFrame进行了一些过滤,效果非常好,得到了期望的行。我使用的代码如下所示:

def my_answer():

    mask1 = census_df["REGION"].between(1, 2)
    mask2 = census_df.index.get_level_values("CTYNAME").str.startswith("Washington")
    mask3 = (census_df["POPESTIMATE2015"] > census_df["POPESTIMATE2014"])
    new_df = census_df[mask1 & mask2 & mask3]
    return pd.DataFrame(new_df.iloc[:, -1])

my_answer()

问题如下:

上述代码返回一个数据框,其中包含索引和第一列,以及两个索引列。我想要的只是这两个索引列。因此,最终答案应该返回一个数据框,其中包含“STNAME”和“CTYNAME”,共5行。


1
你想使用 return new_df.reset_index() 替代 return pd.DataFrame(new_df.iloc[:, 0]) 吗? - jezrael
@jezrael 不行,它会返回所有列,而我不想要。我只想要“STNAME”和“CTYNAME”这两列。此外,我不仅想要它们作为列,我还想要它们作为索引,并且以排序的方式呈现。 - CuriousLearner
2个回答

1
使用列表推导式:
def my_answer():
     mask1 = census_df["REGION"].between(1, 2)
     mask2 = census_df.index.get_level_values("CTYNAME").str.startswith("Washington")
     mask3 = (census_df["POPESTIMATE2015"] > census_df["POPESTIMATE2014"])
     new_df = census_df[mask1 & mask2 & mask3]

     return pd.DataFrame([new_df.index[x] for x in range(len(new_df))])    

my_answer()

输出:

    0              1
 0  Iowa         Washington County
 1  Minnesota    Washington County
 2  Pennsylvania Washington County
 3  Rhode Island Washington County
 4  Wisconsin    Washington County``

0
你可以将 index 转换为 DataFrame:
def my_answer():

    mask1 = census_df["REGION"].between(1, 2)
    mask2 = census_df.index.get_level_values("CTYNAME").str.startswith("Washington")
    mask3 = (census_df["POPESTIMATE2015"] > census_df["POPESTIMATE2014"])
    new_df = census_df[mask1 & mask2 & mask3]
    return pd.DataFrame(new_df.index.tolist(), columns=['STNAME','CTYNAME'])

print (my_answer())

         STNAME            CTYNAME
0          Iowa  Washington County
1     Minnesota  Washington County
2  Pennsylvania  Washington County
3  Rhode Island  Washington County
4     Wisconsin  Washington County

如果想要输出为MultiIndex,需要使用MultiIndex.remove_unused_levels,但它只适用于pandas 0.20.0+版本:
def my_answer():

    mask1 = census_df["REGION"].between(1, 2)
    mask2 = census_df.index.get_level_values("CTYNAME").str.startswith("Washington")
    mask3 = (census_df["POPESTIMATE2015"] > census_df["POPESTIMATE2014"])
    new_df = census_df[mask1 & mask2 & mask3]
    return new_df.index.remove_unused_levels()

print (my_answer())

MultiIndex(levels=[['Iowa', 'Minnesota', 'Pennsylvania', 'Rhode Island', 'Wisconsin'], 
                   ['Washington County']],
           labels=[[0, 1, 2, 3, 4], [0, 0, 0, 0, 0]],
           names=['STNAME', 'CTYNAME'])

AttributeError: 'MultiIndex'对象没有'to_frame'属性。 - CuriousLearner
您所建议的是重置索引,但我认为这对我不起作用。虽然框架的视图符合我的要求,但输出结果并不理想。我希望"STNAME"和"CTYNAME"这两个实体成为索引,而不是列。 - CuriousLearner
@ArchanJoshi - 在pandas中,可以通过return pd.DataFrame(new_df.index.tolist(), columns=['STNAME','CTYNAME']).to_string(index=False)实现,但它会将数据框转换为字符串。 - jezrael
但是默认情况下,如果想要删除DataFrame对象中的索引,则无法删除。 - jezrael
但是如果想要单独查看索引列,则不可能。 - jezrael
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接