将稀疏向量的字符串表示转换为Pandas数据帧

时间:2017-04-28 04:32:13

标签: python pandas sparse-matrix

我有一个向量vec,其中每个元素都是稀疏向量的字符串表示 我想要的输出是具有以下特征的Pandas DataFrame

  

索引vec索引
  :稀疏矢量索引
  :稀疏矢量值

稀疏向量使用格式<feature_index>:<feature_value>进行编码,记录由单个空格分隔。

以下是几行示例数据:

vec = ["70:1.0000 71:1.0000 83:1.0000",
       "3:2.0000 8:2.0000 9:3.0000",
       "3:3.0000 185:1.0000 186:1.0000",
       "3:1.0000 8:1.0000 289:1.0000"]

这是我的预期输出:

          185     186     289       3      70      71       8      83       9
index                                                                        
0         NaN     NaN     NaN     NaN  1.0000  1.0000     NaN  1.0000     NaN
1         NaN     NaN     NaN  2.0000     NaN     NaN  2.0000     NaN  3.0000
2      1.0000  1.0000     NaN  3.0000     NaN     NaN     NaN     NaN     NaN
3         NaN     NaN  1.0000  1.0000     NaN     NaN  1.0000     NaN     NaN

我有一个使用from_recordspivot的工作解决方案,但它似乎笨拙且效率低下:

import pandas as pd

dense = pd.DataFrame()

for i, row in enumerate(vec):
    tups = []
    for entry in row.split(): 
        tups.append(tuple([x for x in entry.split(':')]))

    dense = pd.concat([dense,
                       (pd.DataFrame
                          .from_records(tups, 
                                        index=[i]*len(tups), 
                                        columns=['key','val'])
                          .reset_index()
                          .pivot(index='index', 
                                 columns='key', 
                                 values='val')
                       )
                     ])

任何人都可以建议更清洁的方法,理想情况下更好地使用Pandas功能吗?
我正在使用的实际数据集相当大,所以如果可能的话,我想利用原生Pandas中的性能优化。

注意:
- 输出索引不需要标记为index - 这不一定是纯粹的熊猫解决方案。例如,我看了一些处理稀疏性的sklearn方法,但是它们都不适合解决这个任务。
- 我不确定这是否重要,但在此操作之后,我将结果DataFrame(称之为dense)与另一个DataFrame合并(称之为df), densedf索引作为合并键。因此,在此示例中,vec索引为[0,1,2,3],输出dense需要保留这些索引。

1 个答案:

答案 0 :(得分:1)

我认为您可以使用list comprehensions - 首先进行拆分,然后使用dicts构造函数将其转换为DataFrame

print ([dict([y.split(':') for y in (x.split())]) for x in vec])
[{'83': '1.0000', '70': '1.0000', '71': '1.0000'}, 
 {'8': '2.0000', '3': '2.0000', '9': '3.0000'}, 
 {'185': '1.0000', '186': '1.0000', '3': '3.0000'}, 
 {'289': '1.0000', '8': '1.0000', '3': '1.0000'}]

df = pd.DataFrame([dict([y.split(':') for y in (x.split())]) for x in vec])
print (df)
      185     186     289       3      70      71       8      83       9
0     NaN     NaN     NaN     NaN  1.0000  1.0000     NaN  1.0000     NaN
1     NaN     NaN     NaN  2.0000     NaN     NaN  2.0000     NaN  3.0000
2  1.0000  1.0000     NaN  3.0000     NaN     NaN     NaN     NaN     NaN
3     NaN     NaN  1.0000  1.0000     NaN     NaN  1.0000     NaN     NaN

使用DataFrame和字符串获取NaN,因此需要进行数值投射:

print (type(df.loc[0,'70']))
<class 'str'>

df = df.astype(float)
print (df)
   185  186  289    3   70   71    8   83    9
0  NaN  NaN  NaN  NaN  1.0  1.0  NaN  1.0  NaN
1  NaN  NaN  NaN  2.0  NaN  NaN  2.0  NaN  3.0
2  1.0  1.0  NaN  3.0  NaN  NaN  NaN  NaN  NaN
3  NaN  NaN  1.0  1.0  NaN  NaN  1.0  NaN  NaN

print (type(df.loc[0,'70']))
<class 'numpy.float64'>