从 Dataframe 列生成2D独热编码的numpy矩阵

icomxhvb  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(108)

我有一个pandas数据框架,其中包括学生每学期所修的课程。

data = [['1011', 10, 'Spring-2022','MATH-101'],
        ['1011', 11, 'Summer-2022','BIO-101'],
        ['1011', 12, 'Fall-2022','STAT-102'],
        ['1011', 12, 'Fall-2022','CHEM-101'],
        ['1022', 10, 'Spring-2022','ART-101'],
        ['1022', 10, 'Spring-2022','HIST-102'],
        ['1022', 12, 'Fall-2022','MATH-101'],
       ]
df = pd.DataFrame(data, columns=['StudentID', 'TermID', 'Termname','CourseID'])

print(df)

    StudentID   TermID  Termname      CourseID
0   1011        10      Spring-2022   MATH-101
1   1011        11      Summer-2022   BIO-101
2   1011        12      Fall-2022     STAT-102
3   1011        12      Fall-2022     CHEM-101
4   1022        10      Spring-2022   ART-101
5   1022        10      Spring-2022   HIST-102
6   1022        12      Fall-2022     MATH-101

我试图将其转换为3D numpy数组,其中numpy数组的形状是(没有唯一的学生,没有唯一的术语,没有唯一的课程)。例如,形状为(2,3,6)。
numpy数组的第二维和第三维是一个2D独热编码矩阵,其中行表示所有术语,列表示所有课程。
最终输出:

arr = np.zeros((2,3,6))
arr[0,0,0]=1 #student 1011 Term 10 Course MATH-101
arr[0,1,1]=1 #student 1011 Term 11 Course BIO-101
arr[0,2,2]=1 #student 1011 Term 12 Course STAT-102
arr[0,2,3]=1 #student 1011 Term 12 Course CHEM-101
arr[1,0,4]=1 #student 1022 Term 10 Course ART-101
arr[1,0,5]=1 #student 1022 Term 10 Course HIST-102
arr[1,2,0]=1 #student 1022 Term 12 Course MATH-101

print(arr)

[[[1. 0. 0. 0. 0. 0.]
  [0. 1. 0. 0. 0. 0.]
  [0. 0. 1. 1. 0. 0.]]

 [[0. 0. 0. 0. 1. 1.]
  [0. 0. 0. 0. 0. 0.]
  [1. 0. 0. 0. 0. 0.]]]
mcvgt66p

mcvgt66p1#

你可以在使用pd.factorize之后使用numpy(或者scipy来创建稀疏矩阵):

cols = ['StudentID', 'TermID', 'CourseID']
pos, idx = zip(*[pd.factorize(df[col]) for col in cols])
arr = np.zeros([len(i) for i in idx], dtype='uint8')
arr[tuple(np.stack(pos))] = 1

输出量:

>>> arr
array([[[1, 0, 0, 0, 0, 0],
        [0, 1, 0, 0, 0, 0],
        [0, 0, 1, 1, 0, 0]],

       [[0, 0, 0, 0, 1, 1],
        [0, 0, 0, 0, 0, 0],
        [1, 0, 0, 0, 0, 0]]], dtype=uint8)
avkwfej4

avkwfej42#

使用crosstabstack,然后reshape

a = (pd.crosstab(df['StudentID'],
             [df['CourseID'], df['TermID']])
   .stack(dropna=False)
   .gt(0)
   .to_numpy(dtype=int)
 )

a = a.reshape(df['StudentID'].nunique(), -1, a.shape[1])

输出量:

array([[[0, 0, 0, 0, 1, 0],
        [0, 1, 0, 0, 0, 0],
        [0, 0, 1, 0, 0, 1]],

       [[1, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0]]])

如果需要列的特定顺序,请使用分类或重新排序,并带有:

a = (pd.crosstab(df['StudentID'],
             [df['CourseID'], df['TermID']])
   .stack(dropna=False)
   .gt(0)[df['CourseID'].unique()]
   .to_numpy(dtype=int)
 )

a = a.reshape(df['StudentID'].nunique(), -1, a.shape[1])

输出量:

array([[[1, 0, 0, 0, 0, 0],
        [0, 1, 0, 0, 0, 0],
        [0, 0, 1, 1, 0, 0]],

       [[0, 0, 0, 0, 1, 1],
        [0, 0, 0, 0, 0, 0],
        [1, 0, 0, 0, 0, 0]]])

相关问题