Сортировать матрицу Julia 1.1 по одному из ее столбцов, который содержит строки - PullRequest
5 голосов
/ 26 марта 2019

Как видно из заголовка, мне нужно отсортировать строки определенной матрицы по одному из ее столбцов, желательно на месте, если это вообще возможно.Указанный столбец содержит String s (массив имеет тип Array{Union{Float64,String}}), и в идеале строки должны заканчиваться в алфавитном порядке, определяемом этим столбцом.Строка

sorted_rows = sort!(data, by = i -> data[i,2]),

, где data - моя матрица, выдает ошибку ERROR: LoadError: UndefKeywordError: keyword argument dims not assigned.Указав, какую часть матрицы я хочу отсортировать, и добавив параметр dims=2 (который я предполагаю, это измерение, по которому я хочу отсортировать), а именно

sorted_rows = sort!(data[2:end-1,:], by = i -> data[i,2],dims=2)

просто изменяет сообщение об ошибке на ERROR: LoadError: ArgumentError: invalid index: 01 Suurin yhteinen tekijä ja pienin yhteinen jaettava of type String.Таким образом, компилятор жалуется на то, что строка является недопустимым индексом.

Есть какие-нибудь идеи о том, как можно выполнить этот тип сортировки?Я должен сказать, что в этом случае строка в столбце может начинаться с цифры, но я не против найти решение, которое работает в общем случае.

Я использую Julia 1.1.

Ответы [ 2 ]

7 голосов
/ 26 марта 2019

Вы хотите sortslices, а не sort - последний просто сортирует все столбцы независимо, тогда как первый переставляет целые фрагменты. Во-вторых, функция by не принимает index , она принимает значение , которое собирается сравнивать (и позволяет каким-то образом преобразовать его). Таким образом:

julia> using Random
       data = Union{Float64, String}[randn(100) [randstring(10) for _ in 1:100]]
100×2 Array{Union{Float64, String},2}:
  0.211015  "6VPQbWU5f9"
 -0.292298  "HgvHLkufqI"
  1.74231   "zTCu1U5Vdl"
  0.195822  "O3j43sbhKV"
  ⋮
 -0.369007  "VzFH2OpWfU"
 -1.30459   "6C68G64AWg"
 -1.02434   "rldaQ3e0GE"
  1.61653   "vjvn1SX3FW"

julia> sortslices(data, by=x->x[2], dims=1)
100×2 Array{Union{Float64, String},2}:
  0.229143  "0syMQ7AFgQ"
 -0.642065  "0wUew61bI5"
  1.16888   "12PUn4V4gL"
 -0.266574  "1Z2ONSBP04"
  ⋮
  1.85761   "y2DDANcFCe"
  1.53337   "yZju1uQqMM"
  1.74231   "zTCu1U5Vdl"
  0.974607  "zdiU0sVOZt"

К сожалению, у нас пока нет sortslices!, но вы можете легко создать отсортированный вид с помощью sortperm. Вероятно, это будет не так быстро использовать, но если вам нужна локальность по семантическим причинам, это подойдет.

julia> p = sortperm(data[:,2]);

julia> @view data[p, :]
100×2 view(::Array{Union{Float64, String},2}, [26, 45, 90, 87, 6, 96, 82, 75, 12, 27  …  53, 69, 100, 93, 36, 37, 39, 8, 3, 61], :) with eltype Union{Float64, String}:
  0.229143  "0syMQ7AFgQ"
 -0.642065  "0wUew61bI5"
  1.16888   "12PUn4V4gL"
 -0.266574  "1Z2ONSBP04"
  ⋮
  1.85761   "y2DDANcFCe"
  1.53337   "yZju1uQqMM"
  1.74231   "zTCu1U5Vdl"
  0.974607  "zdiU0sVOZt"

(Если вы хотите на месте по соображениям производительности, я бы порекомендовал использовать DataFrame или аналогичную структуру, которая содержит свои столбцы в качестве независимых однородных векторов - Union{Float64, String} будет медленнее, чем два отдельных вектора с хорошо типизированными данными и sort! использование DataFrame работает с целыми строками так, как вы хотите.)

1 голос
/ 27 марта 2019

Вы можете посмотреть на SortingLab.jl функции быстрой сортировки строк.

]add SortingLab
using SortingLab
idx = fsortperm(data[:,2])
new_data = data[idx]
...