用于数据帧分组的多个索引

时间:2018-04-10 22:54:53

标签: python excel pandas dataframe

我将从示例开始,然后分解正在发生的事情。

这是一个示例输入:

DataFrame:

**Name**    **No.**      **Test**       ***Grade***
Bob        2123320        Math             Nan
Joe        2832883       English           90
John       2139300       Science           85
Bob        2123320        History          93
John       2234903        Math             99

希望输出:

**Name**         ********2139300*********     ********2234903*******
                  Math   English  Science     Math   English  Science 
  John            0       0         85        99        0          0

就像标题所示,我正在尝试应用多个索引。因此,基本上它首先查找每个名称,然后查找每个名称,以查看它有多少不同的号码。在这种情况下,它设置一个阈值至少2个不同的号码(这就是为什么只输出John而Joe / Bob不输出。)

现在,在这些不同的No中。我有一个我想要搜索的特定测试子集,在这种情况下只有{Math,English,Science}。对于这些测试中的每一个,如果有关人员在该编号中进行测试,则应该有一个等级。我希望该等级被输出用于有关测试,并且对于那个人没有采取的测试,我希望它输出某种简单的标记(即如果那个人当天只拿数学,英语和科学输出0)。

因此,实际上,它首先根据不同的编号对人进行索引,并将它们分组。然后它按Test的类型对它们进行索引(我只想要一个子集)。它最终为每个人分配了他们所采用的测试类型的值,并且他们没有为他们输出一个0。

它类似于我之前提到的另一个问题: Grouped Feature Matrix in Python #2- Follow Up

除了现在而不是1和0之外,我还有另一个列,其中包含我想输出的实际值。

谢谢。

编辑:更多样本/输出

 **Name**    **No.**      **Test**       ***Grade***
Bob        2123320        Math             Nan
Joe        2832883       English           90
John       2139300       Science           85
Bob        2123320        History          93
John       2234903        Math             99
Bob        2932848         English         99


  **Name**    2139300        2234903       2123320      2932848
          M   E    S      M   E    S    M   E    S    M   E    S
  John    0   0    85    99   0    0   Nan  Nan  Nan  Nan  Nan Nan
  Bob     Nan Nan  Nan   Nan  nan  Nan 86   0    0    0    99  0

2 个答案:

答案 0 :(得分:1)

您可以使用pivot_table

In [11]: df.pivot_table(values="Grade", index=["Name"], columns=["No.", "Test"])
Out[11]:
No.  2123320 2139300 2234903 2832883
Test History Science    Math English
Name
Bob     93.0     NaN     NaN     NaN
Joe      NaN     NaN     NaN    90.0
John     NaN    85.0    99.0     NaN

使用dropna标志包含所有NaN列:

In [12]: df.pivot_table(values="Grade", index=["Name"], columns=["No.", "Test"], dropna=False)
Out[12]:
No.  2123320                      2139300                      2234903                       2832883
Test English History Math Science English History Math Science English History  Math Science English History Math Science
Name
Bob      NaN    93.0  NaN     NaN     NaN     NaN  NaN     NaN     NaN     NaN   NaN     NaN     NaN     NaN  NaN     NaN
Joe      NaN     NaN  NaN     NaN     NaN     NaN  NaN     NaN     NaN     NaN   NaN     NaN    90.0     NaN  NaN     NaN
John     NaN     NaN  NaN     NaN     NaN     NaN  NaN    85.0     NaN     NaN  99.0     NaN     NaN     NaN  NaN     NaN

并且fill_value = 0

In [13]: df.pivot_table(values="Grade", index=["Name"], columns=["No.", "Test"], dropna=False, fill_value=0)
Out[13]:
No.  2123320                      2139300                      2234903                      2832883
Test English History Math Science English History Math Science English History Math Science English History Math Science
Name
Bob        0      93    0       0       0       0    0       0       0       0    0       0       0       0    0       0
Joe        0       0    0       0       0       0    0       0       0       0    0       0      90       0    0       0
John       0       0    0       0       0       0    0      85       0       0   99       0       0       0    0       0

答案 1 :(得分:1)

让我们使用:

将数据框过滤为仅与您有关的记录

df_out = df[df.groupby(['Name'])['No.'].transform(lambda x: x.nunique() > 1)]

现在,使用set_indexunstackreindex重塑数据框:

df_out.set_index(['Name','No.','Test'])['Grade'].sum(level=[0,1,2])\
      .unstack(-1, fill_value=0)\
      .reindex(['Math','English','Science'], axis=1, fill_value=0)\
      .unstack(-1, fill_value=0).swaplevel(0, 1, axis=1)\
      .sort_index(1)

输出:

No.  2123320              2139300              2234903              2932848             
Test English Math Science English Math Science English Math Science English Math Science
Name                                                                                    
Bob        0    0       0       0    0       0       0    0       0      99    0       0
John       0    0       0       0    0      85       0   99       0       0    0       0