【问题标题】:Convert string representations of sparse vectors into Pandas dataframe将稀疏向量的字符串表示形式转换为 Pandas 数据帧
【发布时间】:2017-04-28 13:23:08
【问题描述】:

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

indexvec index
columns:稀疏向量索引
values:稀疏向量值

稀疏向量以<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
- 这不一定是纯粹的 Pandas 解决方案。例如,我查看了一些处理稀疏性的sklearn 方法,但它们似乎都不适合解决这个任务。
- 我不确定这是否重要,但在此操作之后,我使用densedf 索引将生成的DataFrame(称为dense)与另一个DataFrame(称为df)合并作为合并键。所以在这个例子中,vec 索引是[0,1,2,3],输出dense 需要保留这些索引。

【问题讨论】:

  • 您有机会以其他格式保存您的vec 吗?你的源数据集是什么?是稀疏矩阵吗?
  • 不幸的是,我无法以它的格式处理 vec - 它来自我无法控制的上游进程。

标签: python pandas sparse-matrix


【解决方案1】:

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

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

使用NaNs 和字符串获取DataFrame,因此需要进行数字转换:

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'>

【讨论】:

  • 谢谢@jezrael。您的解决方案比我的解决方案快两个数量级(5.52 毫秒对 648 毫秒)。真不错!
  • 很高兴能帮上忙!周末愉快!
猜你喜欢
  • 1970-01-01
  • 2016-08-03
  • 2016-09-19
  • 2016-08-03
  • 2013-12-25
  • 2016-09-09
  • 2019-12-05
  • 2021-02-01
  • 1970-01-01
相关资源
最近更新 更多