英文:
capture column name as value in pandas
问题
我只想在新列中以值的形式捕获主题名称(列名),在重新评估后学生的成绩有所改善。
我有重新评估前的数据集:
| 姓名 | 班级 | 考试 | 数学 | 物理 | 化学 | 
|---|---|---|---|---|---|
| 约翰 | 10年级 | 模型 1 | 98 | 78 | 75 | 
| 鲍勃 | 06年级 | 期中考试 | 65 | 72 | 92 | 
| 罗斯 | 06年级 | 模型 2 | 91 | 70 | 54 | 
| 迈克尔 | 07年级 | 模型 1 | 72 | 90 | 45 | 
现在我有重新评估后的数据集,有些学生的成绩有所提高,其他学生的成绩有新数据,
| 姓名 | 班级 | 考试 | 数学 | 物理 | 化学 | 
|---|---|---|---|---|---|
| 约翰 | 10年级 | 模型 1 | 98 | 78 | 87 | 
| 鲍勃 | 06年级 | 期中考试 | 65 | 91 | 92 | 
| 罗斯 | 06年级 | 模型 2 | 91 | 70 | 54 | 
| 迈克尔 | 07年级 | 模型 1 | 100 | 90 | 45 | 
| 萨姆 | 08年级 | 期中考试 | 43 | 62 | 80 | 
| 詹姆斯 | 10年级 | 模型 ` | 76 | 66 | 96 | 
| 亨利 | 09年级 | 模型 1 | 34 | 91 | 70 | 
现在,我们需要合并这两个数据集,并标记哪些行已更新,以及哪些列已更新,因此,合并后的数据集看起来像这样,
| 姓名 | 班级 | 考试 | 数学 | 物理 | 化学 | 
|---|---|---|---|---|---|
| 约翰 | 10年级 | 模型 1 | 98 | 78 | 75 | 
| 鲍勃 | 06年级 | 期中考试 | 65 | 72 | 92 | 
| 罗斯 | 06年级 | 模型 2 | 91 | 70 | 54 | 
| 迈克尔 | 07年级 | 模型 1 | 72 | 90 | 45 | 
| 约翰 | 10年级 | 模型 1 | 98 | 78 | 87 | 
| 鲍勃 | 06年级 | 期中考试 | 65 | 91 | 92 | 
| 罗斯 | 06年级 | 模型 2 | 91 | 70 | 54 | 
| 迈克尔 | 07年级 | 模型 1 | 100 | 90 | 45 | 
| 萨姆 | 08年级 | 期中考试 | 43 | 62 | 80 | 
| 詹姆斯 | 10年级 | 模型 ` | 76 | 66 | 96 | 
| 亨利 | 09年级 | 模型 1 | 34 | 91 | 70 | 
现在,最终输出应该如下所示,有两列新列,我能消除重复项并添加新列任何改进,但我卡在添加另一新列改进的科目。
| 姓名 | 班级 | 考试 | 数学 | 物理 | 化学 | 任何改进 | 改进的科目 | 
|---|---|---|---|---|---|---|---|
| 约翰 | 10年级 | 模型 1 | 98 | 78 | 87 | 是 | 化学 | 
| 鲍勃 | 06年级 | 期中考试 | 65 | 91 | 92 | 是 | 物理 | 
| 罗斯 | 06年级 | 模型 2 | 91 | 70 | 54 | 否 | 无改进 | 
| 迈克尔 | 07年级 | 模型 1 | 100 | 90 | 45 | 是 | 数学 | 
| 萨姆 | 08年级 | 期中考试 | 43 | 62 | 80 | 新条目 | 新条目 | 
| 詹姆斯 | 10年级 | 模型 ` | 76 | 66 | 96 | 新条目 | 新条目 | 
| 亨利 | 09年级 | 模型 1 | 34 | 91 | 70 | 新条目 | 新条目 | 
以下是我用于此目的的代码,
通过连接姓名
<details>
<summary>英文:</summary>
I just want to capture the subject name (column name) as value in new column where there is some improvements in the students marks after re-evaluation.
I have the dataset before re-evaluation:
|   name  |    class   |   exam  | maths | physics | chemistry |
|---------|------------|---------|-------|---------|-----------|
|  John   | Grade - 10 | model 1 |  98   |   78    |    75     |
|  Bob    | Grade - 06 | mid term|  65   |   72    |    92     |
|  Rose   | Grade - 06 | model 2 |  91   |   70    |    54     |
| Michael | Grade - 07 | model 1 |  72   |   90    |    45     |
Now I have the dataset after re-evaluation, there are some improvements in some students marks, and there are new data on other students marks who took their exam recently,
|   name  |    class   |   exam  |   maths    |   physics  |   chemistry  |
|---------|------------|---------|------------|------------|--------------|
|  John   | Grade - 10 | model 1 |    98      |     78     |    **87**    |
|  Bob    | Grade - 06 | mid term|    65      |   **91**   |      92      |
|  Rose   | Grade - 06 | model 2 |    91      |     70     |      54      |
| Michael | Grade - 07 | model 1 |  **100**   |     90     |      45      |
|  Sam    | Grade - 08 | mid term|    43      |     62     |      80      |
|  James  | Grade - 10 | model ` |    76      |     66     |      96      |
| Henry   | Grade - 09 | model 1 |    34      |     91     |      70      |
Now, we need to concat these two datasets, and mark which row is updated, and which column got updated, so, the concatenated dataset looks like this,
|   name  |    class   |   exam  |   maths    |   physics  |   chemistry  |
|---------|------------|---------|------------|------------|--------------|
|  John   | Grade - 10 | model 1 |    98      |     78     |      75      |
|  Bob    | Grade - 06 | mid term|    65      |     72     |      92      |
|  Rose   | Grade - 06 | model 2 |    91      |     70     |      54      |
| Michael | Grade - 07 | model 1 |    72      |     90     |      45      |
|  John   | Grade - 10 | model 1 |    98      |     78     |    **87**    |
|  Bob    | Grade - 06 | mid term|    65      |   **91**   |      92      |
|  Rose   | Grade - 06 | model 2 |    91      |     70     |      54      |
| Michael | Grade - 07 | model 1 |  **100**   |     90     |      45      |
|  Sam    | Grade - 08 | mid term|    43      |     62     |      80      |
|  James  | Grade - 10 | model ` |    76      |     66     |      96      |
| Henry   | Grade - 09 | model 1 |    34      |     91     |      70      |
Now, the final output should look like this, with 2 new columns, I was able to eliminate the duplicates and added the new columns **any improvement**, but I got stuck on adding the other new column **improved subject**
|   name  |    class   |   exam  | maths  |physics|chemistry|any improvement|improved subject|
|---------|------------|---------|--------|-------|---------|---------------|----------------|
|  John   | Grade - 10 | model 1 |  98    |  78   | **87**  |      Yes      |    chemistry   |
|  Bob    | Grade - 06 | mid term|  65    |**91** |   92    |      Yes      |    physics     |
|  Rose   | Grade - 06 | model 2 |  91    |  70   |   54    |      No       | no improvement |
| Michael | Grade - 07 | model 1 |**100** |  90   |   45    |      Yes      |     maths      |
|  Sam    | Grade - 08 | mid term|  43    |  62   |   80    |   New Entry   |    new entry   |
|  James  | Grade - 10 | model ` |  76    |  66   |   96    |   New Entry   |    new entry   |
| Henry   | Grade - 09 | model 1 |  34    |  91   |   70    |   New Entry   |    new entry   |
Below is the code, I used for this,
added primary key column by concatenating name, class, exam and secondary key column by concatenating maths,physics,chemistry.
dupedf = concatdf.loc[concatdf.duplicated(subset=['PrimaryKey', 'SecondaryKey'],keep=False)]
dupedf1 = concatdf.loc[concatdf.duplicated(subset=['PrimaryKey'],keep=False)]
for i,j in dupedf.iterrows():
for k,l in dupedf1.iterrows():
if l['PrimaryKey'] == j['PrimaryKey']:
        dupedf = dupedf.drop_duplicates(subset=['PrimaryKey','SecondaryKey'],keep='last')
        dupedf['any improvement'] = 'No'
        # dupedf['improved subject'] = ' '
    else:
        dupedf1 = dupedf1.drop_duplicates(subset=['SecondaryKey'],keep=False)
        
        dupedf1 = dupedf1.drop_duplicates(subset=['PrimaryKey'],keep='last')
        dupedf1['any improvement'] = 'Yes'
       # dupedf1['improved subject'] = 'column name'
in the above code, I am iterating only the rows which exists in both before & after re-evaluation datasets. iterating row by row to have fill the 2 new columns **any improvement & improved subject.** **I was able to achieve for any improvement column, but I need help with improved subject column.**
</details>
# 答案1
**得分**: 1
```python
# 一个可能的解决方案:
pkeys = ["name", "class", "exam"]
delta = df1.set_index(pkeys).sub(df2.set_index(pkeys)).lt(0)
mapper = { # 这将处理多个科目的改进
    k: "/".join(delta.columns[delta.loc[k]]) # 根据需要更改分隔符
    for k in delta.index if any(delta.loc[k])
}
tmp = pd.concat([df1.set_index(pkeys), df2.set_index(pkeys)])
m = tmp.index.duplicated(keep=False)
tmp["any improvement"] = (
    pd.Index(tmp.index.isin(mapper))
    .map({True: "是", False: "否"}).where(m, "新条目")
)
tmp["improved subject"] = (
    tmp.index.map(mapper).fillna("没有改进").where(m, "新条目")
)
out = tmp.query("~index.duplicated(keep='last')").reset_index()
# 输出:
print(out)
   姓名       班级    考试      数学     物理    化学  任何改进  改进科目
0  约翰  10年级  模型1    98    78      87          是              化学
1  鲍勃   06年级  中期    65    91      92          是              物理
2  罗斯   06年级  模型2   91    70      54          否              没有改进
3  迈克尔  07年级  模型1  100    90      45          是              数学
4  山姆   08年级  中期    43    62      80   新条目     新条目
5  詹姆斯  10年级  模型`    76    66      96   新条目     新条目
6  亨利   09年级  模型1    34    91      70   新条目     新条目
英文:
A possible solution :
pkeys = ["name", "class", "exam"]
delta = df1.set_index(pkeys).sub(df2.set_index(pkeys)).lt(0)
mapper = { # this will handle multiple subjects improvements
    k: "/".join(delta.columns[delta.loc[k]]) # change the sep if needed
    for k in delta.index if any(delta.loc[k])
}
tmp = pd.concat([df1.set_index(pkeys), df2.set_index(pkeys)])
m = tmp.index.duplicated(keep=False)
tmp["any improvement"] = (
    pd.Index(tmp.index.isin(mapper))
    .map({True: "Yes", False: "No"}).where(m, "New Entry")
)
tmp["improved subject"] = (
    tmp.index.map(mapper).fillna("no improvement").where(m, "New Entry")
)
out = tmp.query("~index.duplicated(keep='last')").reset_index()
Output :
print(out)
   name      class     exam  maths  physics  chemistry any improvement improved subject
   John Grade - 10  model 1     98       78         87             Yes        chemistry
    Bob Grade - 06 mid term     65       91         92             Yes          physics
   Rose Grade - 06  model 2     91       70         54              No   no improvement
Michael Grade - 07  model 1    100       90         45             Yes            maths
    Sam Grade - 08 mid term     43       62         80       New Entry        New Entry
  James Grade - 10  model `     76       66         96       New Entry        New Entry
  Henry Grade - 09  model 1     34       91         70       New Entry        New Entry
With the Styler to expose the improvements :
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论