【问题标题】:Merging 2 csv data sets with Python a common ID column- one csv has multiple records for a unique ID将 2 个 csv 数据集与 Python 合并为一个公共 ID 列 - 一个 csv 具有多个唯一 ID 记录
【发布时间】:2017-08-07 04:31:02
【问题描述】:

我是 Python 的新手。非常感谢任何支持

我尝试使用 Student_ID 列合并两个 csv 文件并创建一个新的 csv 文件。

csv 1 : 每个条目都有一个唯一的 studentID

Student_ID    Age        Course       startYear
119           24         Bsc          2014

csv2:一个学生 ID 有多个记录,因为它为学生正在学习的每个科目都有一个新条目

Student_ID            sub_name       marks      Sub_year_level
119                   Botany1        60         2
119                   Anatomy        70         2
119                   cell bio       75         3
129                   Physics1       78         2
129                   Math1          60         1 

我想合并这两个 csv 文件,以便我拥有来自 csv1 的所有记录和列以及我想从 csv2 获得每个学生的每个 subject_year_level 的平均分数(必须计算)的新创建的列。所以最终的 csv 文件在所有记录中都会有唯一的 Student_Ids

我希望我的新输出 csv 文件看起来像什么:

Student_ID  Age  Course  startYear  level1_avg_mark  levl2_avg_mark  levl3_avgmark
119         24   Bsc     2014       60               65              70

【问题讨论】:

  • 感谢您编辑 piRSquared

标签: python csv pandas merge


【解决方案1】:

您可以将pivot_tablejoin 一起使用:

注意:参数fill_valueNaN 替换为0,如果没有必要将其删除,默认聚合函数为mean

df2 = df2.pivot_table(index='Student_ID',  \
                      columns='Sub_year_level',  \
                      values='marks', \
                      fill_value=0) \
         .rename(columns='level{}_avg_mark'.format)
print (df2)
Sub_year_level  level1_avg_mark  level2_avg_mark  level3_avg_mark
Student_ID                                                       
119                           0               65               75
129                          60               78                0

df = df1.join(df2, on='Student_ID')
print (df)
   Student_ID  Age Course  startYear  level1_avg_mark  level2_avg_mark  \
0         119   24    Bsc       2014                0               65   

   level3_avg_mark  
0               75  

编辑:

需要自定义函数:

print (df2)
   Student_ID  sub_name  marks  Sub_year_level
0         119   Botany1      0               2
1         119   Botany1      0               2
2         119   Anatomy     72               2
3         119  cell bio     75               3
4         129  Physics1     78               2
5         129     Math1     60               1


f = lambda x:  x[x != 0].mean()
df2 = df2.pivot_table(index='Student_ID',columns='Sub_year_level', values='marks',aggfunc=f)
        .rename(columns='level{}_avg_mark'.format).reset_index()
print (df2)
Sub_year_level  Student_ID  level1_avg_mark  level2_avg_mark  level3_avg_mark
0                      119              NaN             72.0             75.0
1                      129             60.0             78.0              NaN

【讨论】:

  • 这似乎有效。我一直在努力写一整天的代码。非常感谢。你们和 Python 都很棒!
  • 如果我或其他答案有帮助,请不要忘记accept。谢谢。
  • 但是好的,你能解释更多吗?最好的方法是编辑具有所需输出的问题。谢谢。
  • 能否请您建议我如何编辑此代码以获得避免 0 或未输入标记的平均标记。例如,假设一个学生 ID 的 subject_level_2 的三个分数条目分别为 0、72、0,但平均计算结果为 36,这会误导学生的表现,因为这两个零很可能是未输入分数的科目。所以在这种情况下,我希望平均值为 72,忽略零标记。任何建议将不胜感激
  • 当然,等一下。
【解决方案2】:

您可以使用groupby 计算每个级别的平均分数。
然后unstack 在一行中获取所有级别。
rename 列。

完成后,groupby + unstack 会方便地将Student_ID 留在索引中,以便轻松使用join。剩下的就是执行join 并指定on 参数。

d1.join(
    d2.groupby(
        ['Student_ID', 'Sub_year_level']
    ).marks.mean().unstack().rename(columns='level{}_avg_mark'.format),
    on='Student_ID'
)

【讨论】:

  • 这看起来很不错。为了编写大量代码,我已经苦苦挣扎了一整天。这似乎有效。非常感谢。你们和 Python 都很棒!
猜你喜欢
  • 2020-01-10
  • 1970-01-01
  • 2021-01-13
  • 2020-06-28
  • 2021-07-07
  • 2016-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多