在列中插入条件行

Sli*_*Jim 5 python numpy rows conditional-statements pandas

我目前有一个跟踪已完成 5 次测试的数据集,但是它只显示那些已完成测试的人,而不是那些尚未参加的人 - 示例如下:

 Name   Test    Completed
John    Math-Test1  Yes
John    Math-Test2  Yes
John    Math-Test3  Yes
John    Math-Test4  Yes
John    Math-Test5  Yes
Lauren  Math-Test1  Yes
Lauren  Math-Test2  Yes
Lauren  Math-Test3  Yes
Tom     Math-Test1  Yes
Tom     Math-Test2  Yes
Tom     Math-Test3  Yes
Tom     Math-Test4  Yes
Tom     Math-Test5  Yes
Run Code Online (Sandbox Code Playgroud)

如您所见,Lauren 尚未参加“Math-Test4”和“Math-Test5”测试,因此她的名字没有出现。我想添加一个选项,让“已完成”列在有人尚未完成测试时显示“否”。

所需的输出如下:

Name    Test    Completed
John    Math-Test1  Yes
John    Math-Test2  Yes
John    Math-Test3  Yes
John    Math-Test4  Yes
John    Math-Test5  Yes
Lauren  Math-Test1  Yes
Lauren  Math-Test2  Yes
Lauren  Math-Test3  Yes
*Lauren Math-Test4  No* - Add these rows automatically
*Lauren Math-Test5  No*
Tom     Math-Test1  Yes
Tom     Math-Test2  Yes
Tom     Math-Test3  Yes
Tom     Math-Test4  Yes
Tom     Math-Test5  Yes
Run Code Online (Sandbox Code Playgroud)

如何使用 Python/Pandas/Numpy 实现这一点?

感谢所有可以提供帮助的人!

编辑 - 更新:在尝试@Scott Boston 的代码后,我得到了这个:

idx = pd.MultiIndex.from_product([df['Name'].unique(), 
                                  df['Test'].unique()], 
                                 names=['Name','Test'])

newidx = idx[~idx.isin(df.set_index(['Name','Test']).index)]
pd.concat([df,
         newidx.to_series().reset_index().assign(Completed="No*")[['Name','Test','Completed']]], ignore_index=True)
Run Code Online (Sandbox Code Playgroud)

输出:

Name1   Test    Completed
John    Math-Test1      Yes
John    Math-Test2      Yes
John    Math-Test3      Yes
John    Math-Test4      Yes
John    Math-Test5      Yes
Lauren  Math-Test1      Yes
Lauren  Math-Test2      Yes
Lauren  Math-Test3      Yes
Tom     Math-Test1      Yes
Tom     Math-Test2      Yes
Tom     Math-Test3      Yes
Tom     Math-Test4      Yes
Tom     Math-Test5      Yes
John    Math-Test3      No*
John    Math-Test4      No*
John    Math-Test5      No*
John    Math-Test2      No*
Lauren  Math-Test3      No*
Lauren  Math-Test4      No*
Lauren  Math-Test5      No*
Lauren  Math-Test2      No*
Lauren  Math-Test5      No*
Lauren  Math-Test1      No*
Lauren  Math-Test2      No*
Lauren  Math-Test4      No*
Lauren  Math-Test5      No*

Run Code Online (Sandbox Code Playgroud)

现在只需要找到删除所需输出的不需要的行的方法。

Sco*_*ton 3

尝试一下,让我们使用带有from_product, set_index, 和reindex,的多重索引

此方法适用于所有“看到”的值,如果没有看到某个值,那么您需要在 from_product 方法中使用硬编码列表:

idx = pd.MultiIndex.from_product([df['Name'].unique(), 
                                  df['Test'].unique()], 
                                 names=['Name','Test'])

df.set_index(['Name','Test']).reindex(idx, fill_value='No*').reset_index()
Run Code Online (Sandbox Code Playgroud)

输出:

      Name        Test Completed
0     John  Math-Test1       Yes
1     John  Math-Test2       Yes
2     John  Math-Test3       Yes
3     John  Math-Test4       Yes
4     John  Math-Test5       Yes
5   Lauren  Math-Test1       Yes
6   Lauren  Math-Test2       Yes
7   Lauren  Math-Test3       Yes
8   Lauren  Math-Test4       No*
9   Lauren  Math-Test5       No*
10     Tom  Math-Test1       Yes
11     Tom  Math-Test2       Yes
12     Tom  Math-Test3       Yes
13     Tom  Math-Test4       Yes
14     Tom  Math-Test5       Yes
Run Code Online (Sandbox Code Playgroud)

更新

idx = pd.MultiIndex.from_product([df['Name'].unique(), 
                                  df['Test'].unique()], 
                                 names=['Name','Test'])

newidx = idx[~idx.isin(df.set_index(['Name','Test']).index)]
pd.concat([df,
         newidx.to_series().reset_index().assign(Completed="No*")[['Name','Test','Completed']]], sort=True, ignore_index=True)
Run Code Online (Sandbox Code Playgroud)