【问题标题】:Vectorizing set operations for string-valued cell arrays in MATLAB/Octave在 MATLAB/Octave 中向量化字符串值元胞数组的集合运算
【发布时间】:2013-07-03 20:06:48
【问题描述】:

我有一个大型数据集X,其中包含调查对象的人口统计信息。数据主要是分类数据,因此X 中的每一行都包含一组字符串值特征,例如单个受访者的性别、种族、兴趣等。 X 的每一列都是一个响应类别。我已将此数据集加载到 MATLAB/Octave 中的一个大单元格数组中(两者都进行了测试)。我想测量数据集中每个样本与每个其他样本之间的 Jaccard 距离。基本上我想做的是这样的:

dist = zeros(size(X,1));    % Initialize my distance matrix
for ii = 1:size(X,1)
    for jj = ii:size(X,1)   % Only need the upper triangle since dist is symmetric
        % Find the Jaccard distance between the ii-th and jj-th respondent
        dist(ii,jj) = 1 - numel(intersect(X(ii,:), X(jj,:))) / numel(union(X(ii,:), X(jj,:)));
    end
end

显然我想对代码进行矢量化处理。我曾尝试使用cellfunbsxfun 进行矢量化,但是当我执行以下操作时:

res = cellfun('intersect', X, X, 'UniformOutput', false);

我得到一个与X 大小相同的单元格数组,其中 (i,j) 元素等价于intersect(X(i,j), X(i,j));基本上是 (i-j) 单元格中的唯一字符。这对我没有帮助。当我尝试时:

res = bsxfun('intersect', X, X);

我得到一个长单元数组,其中包含(我认为)X 中的任何单元格采用的所有唯一值。这对我也没有帮助。

我想要一个解决方案,使我能够在讨论开始时对代码进行矢量化。如果这样做更容易,那么找到X 的子集与X 中任何一行的最小(或最大)Jaccard 距离的代码将正是我所需要的。

提前致谢!

编辑: 将循环代码更改为仅计算 dist 的上三角形。仍然需要很长时间,而且它是非矢量化的事实让我在哲学层面上感到困惑。

编辑:X 的第一个元素,通过键入 X(1,:) 给出:

ans =
{
  [1,1] = Non - U.S. Citizen
  [1,2] = Denied
  [1,3] = M
  [1,4] = CHINA
  [1,5] = Full Time
  [1,6] = D-Asian American or Pacific Islander
  [1,7] = 
  [1,8] = 
  [1,9] = MSME
  [1,10] = 
}

这只是我在等待实际调查结果时用于开发算法的测试数据,但调查结果将具有相似的形式。

编辑:来自X 的更多数据,但为CSV 格式,如下所示:

Non - U.S. Citizen,Denied,M,INDIA,Full Time,E-Other,,,MSME,
Non - U.S. Citizen,Denied,F,INDIA,Full Time,D-Asian American or Pacific Islander,,,MSME,DESIGN
Non - U.S. Citizen,Denied,M,INDIA,Full Time,E-Other,,,MS,
Non - U.S. Citizen,Denied,M,IRAN,Full Time,B-Caucasian American Non-Hispanic,,,PhD,NANO
Non - U.S. Citizen,Left Without Degree,M,JORDAN,Full Time,E-Other,,,,
Non - U.S. Citizen,Denied,F,IRAN,Full Time,E-Other,,,PhD,BIOENG
,Not Attending,M,,Full Time,,,,PhD,
Non - U.S. Citizen,Not Attending,F,IRAN,Full Time,I-International Student,,,PhD,
Non - U.S. Citizen,Denied,M,BANGLADESH,Full Time,E-Other,,,PhD,NANO
Non - U.S. Citizen,Denied,M,BANGLADESH,Full Time,E-Other,,,MS,

【问题讨论】:

  • 您发布的 for 循环代码是否有效?
  • 确实如此,但在数千个元素长的数据集上运行需要太长时间。我想我可以通过只计算对称距离矩阵的上(或下)三角形来节省一半的时间,但这仍然需要几个小时。
  • 你能给出一个 X 的小样本,比如说 10 行吗?
  • 你有统计工具箱吗?它包括一个名为pdist 的函数,它有一个选项'jaccard'
  • @Schorsch 我不知道pdist。我现在正在尝试使用它,但收到错误“x 必须是非空矩阵”。我认为这意味着我不能在 X 中包含空元素,所以我将它们全部替换为 X(cellfun('isempty',X)) = 0 并且我仍然得到相同的错误。 pdist 是否适用于字符串值向量?

标签: matlab set octave vectorization


【解决方案1】:

这可能是一种解决方法,我将在单行数据上进行说明:

a={'Non - U.S. Citizen','Denied','M','INDIA','Full Time','E-Other','','','MSME',''}

对每个单元格元素求和,这会将字符串转换为双精度值并对它们的值求和。假设非唯一总和结果的可能性很小(如果没有可以实施的技巧,但我怀疑它实际上会发生),它将起作用:

b=cellfun(@sum,a,'un',0)

现在每个单元格元素都有一个数字,您可以使用 cell2mat 获取矩阵和 \ 或 pdist 等...

【讨论】:

  • 这让我到了那里,但我不得不稍微改变一下。最终起作用的命令(并给了我一个可以转换为矩阵的数字元胞数组)是B = cellfun('sum', cellfun('toascii', X, 'UniformOutput', false));。我必须先将每个单元格中的字符转换为它们的 ascii 表示,然后对它们求和。
  • 而不是直接取和,转换为双精度数并将每个单元格元素乘以相同长度的某个向量。这会将每个字母的值乘以某个数字,该数字仅取决于字母在向量中的位置。然后总结结果。现在每个词都将与其他词非常不同。例如,如果我有两个具有相同总和的单词,例如: 'ad' , 'bc' ,现在乘以 v=[1 10] 和 sum,你将得到 sum(double('ad'). *[1 10]) vs sum(double('bc').*[1 10]),它们有不同的和(1097和1088)......
猜你喜欢
  • 1970-01-01
  • 2011-07-08
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多