如何重新排列此多索引熊猫数据框的行顺序?

时间:2021-02-17 22:22:12

标签: python pandas database dataframe pivot-table

非常感谢任何提示。 我从以下名为 years69_19 的数据框开始: years69_19

然后,我创建了一堆不同的数据框,其中包含来自 years69_19 的数据,以“Fied”名称分隔。这是我如何做到这一点的示例(某些部门为同一部门有多个标签,因此我使用 | 运算符来查找所有这些标签): separating by field

然后,我将新数据帧放入名为 listofdeps 的列表中。我还制作了一个包含与 listofdeps 对应的字符串的列表,这只是为了正确地为数据框添加标题。 here's the list of dataframes and string labels

最后,我遍历了 listofdeps,并旋转了每个数据帧。这是我的代码:

newlistofdeps = []

for dataframes, deptname in zip(listofdeps, depstrings):
    newlabel =  deptname + ' Department at [REDACTED]'
    dataframes[newlabel] = 1
    deptable = pd.pivot_table(dataframes[['Year', 'Gender', 'Ethnicity', newlabel]], index=['Gender', 'Ethnicity'], columns = ['Year'], aggfunc=np.sum, fill_value=0)
    newlistofdeps.append(deptable)

现在我有一个列表 newlistofdeps,它有每个部门(字段)的数据框,它看起来像这样: example of first dataframe in newlistofdeps

Stackoverflow 社区,我需要以下方面的帮助:

  1. 我需要像这样重新排列种族索引:“亚洲人”、“黑人”、“奇卡诺/墨西哥裔美国人”、“其他西班牙裔/拉丁裔”、“白人”、“其他”、“国际” . 我尝试了很多不同的方法,比如 df.reindex 和使用“级别”,但我一直无法弄清楚如何做到这一点。

  2. 我需要这样做,以便对于 newlistofdeps 中的每个数据框,上面列出的每个种族都会出现,即使该部门中没有该种族的行。 这是我的意思的一个例子。 enter image description here 在这个部门,没有任何奇卡诺/墨西哥裔美国女性或黑人男性。但是,我仍然需要这些组的行,它们将全部填充为 0。 我实际上不知道如何解决这个问题,我在想也许可以用这种格式创建一个数据框,其中所有种族都填充 0,然后将每个数据框与该数据框合并,这样丢失的种族仍然有行。有什么想法吗?

谢谢!!!

1 个答案:

答案 0 :(得分:0)

似乎您在执行交叉制表方面走了很长的路。您可以简单地使用 pd.crosstab 来完成您手动执行的所有繁重工作。

数据创建

import pandas as pd
import numpy as np
import itertools

ethnicities = ['Asian', 'Black', 'Chicano/Mexican-American', 'Other Hispanic/Latino', 'White', 'Other', 'Interational']
fields = ["economics", "physics", "political sciences", "chemistry", "english"]
sexes = ["M", "F"]
years = [2000, 2001, 2002, 2003]

records = itertools.product(ethnicities, fields, sexes, years)
base_df = pd.DataFrame(records, columns=["ethnicity", "field", "sex", "year"])

print(base_df.head(10))

  ethnicity      field sex  year
0     Asian  economics   M  2000
1     Asian  economics   M  2001
2     Asian  economics   M  2002
3     Asian  economics   M  2003
4     Asian  economics   F  2000
5     Asian  economics   F  2001
6     Asian  economics   F  2002
7     Asian  economics   F  2003
8     Asian    physics   M  2000
9     Asian    physics   M  2001

base_df 就是我们所有类别的笛卡尔积。因此,在这个变量中,我们为种族、领域、性别和年份的每一个独特组合都有一行。现在我们有了这个,我们可以对这个数据帧进行采样,使我们的数据更加真实。我将对我们的数据进行欠采样,以确保数据中完全缺失的某些组合区域与您正在处理的数据更加相似。

df = base_df.sample(50, replace=True)

print(df.head())
                 ethnicity               field sex  year
183                  White  political sciences   F  2003
228                  Other           chemistry   F  2000
38                   Asian             english   F  2002
166                  White           economics   F  2002
146  Other Hispanic/Latino           chemistry   M  2002

现在我们有了一个很好的示例数据集,我们可以使用 pd.crosstab 来获取您在问题中计算的计数。我正在设置参数 dropna=False 这告诉熊猫不要丢弃完全缺失的组合,而是用 0 填充缺失的观察。

xtab = pd.crosstab(index=[df["field"], df["sex"], df["ethnicity"]], columns=df["year"], dropna=False)

print(xtab.head(10))
year                                    2000  2001  2002  2003
field     sex ethnicity                                       
chemistry F   Asian                        0     0     0     0
              Black                        0     0     0     0
              Chicano/Mexican-American     0     0     0     0
              Interational                 0     0     0     1
              Other                        1     0     0     0
              Other Hispanic/Latino        0     0     1     0
              White                        1     0     0     0
          M   Asian                        0     1     0     0
              Black                        0     0     0     0
              Chicano/Mexican-American     0     1     0     0

然后你就有了我们所有类别的交叉表,同时也代表了缺失的类别组合。

为了进行比较,以下是您设置 dropna=True 时发生的情况(我们将删除具有 0 个观察值的类别组合 - 例如您发布的问题)。

xtab = pd.crosstab(index=[df["field"], df["sex"], df["ethnicity"]], columns=df["year"], dropna=True)

print(xtab.head(10))
year                                    2000  2001  2002  2003
field     sex ethnicity                                       
chemistry F   Interational                 0     0     0     1
              Other                        1     0     0     0
              Other Hispanic/Latino        0     0     1     0
              White                        1     0     0     0
          M   Asian                        0     1     0     0
              Chicano/Mexican-American     0     1     0     0
              Other Hispanic/Latino        1     2     1     0
              White                        0     1     0     1
economics F   Asian                        0     0     0     1
              Black                        0     1     0     0

请注意,对于 dropna=True,我们现在缺少某些分类组合,因为在我们的样本中未观察到它们。

要更改行的顺序,最简单的方法是按照您期望的顺序显式构造一个新的 MultiIndex,然后从那里开始。

# define the order of categories for each level
new_index = pd.MultiIndex.from_product([
    ["economics", "physics", "political sciences", "chemistry", "english"],
    ["M", "F"],
    ['Asian', 'Black', 'Chicano/Mexican-American', 'Other Hispanic/Latino', 'White', 'Other', 'Interational']],
    names=["field", "sex", "ethnicity"]
)

# use the new index to reorder the data
reordered_xtab = xtab.reindex(new_index)

print(reordered_xtab.head(10))
year                                    2000  2001  2002  2003
field     sex ethnicity                                       
economics M   Asian                        0     0     0     0
              Black                        0     0     0     0
              Chicano/Mexican-American     0     0     1     1
              Other Hispanic/Latino        0     0     0     0
              White                        0     1     1     0
              Other                        0     1     0     0
              Interational                 0     0     0     0
          F   Asian                        0     0     0     0
              Black                        0     0     0     0
              Chicano/Mexican-American     0     0     0     1

现在一切都遵循我在 new_index 中定义的顺序,而不是字母顺序,这是 Pandas 在计算 crosstab 时的默认顺序。