Я никогда не делал ничего подобного, но, похоже, он работает правильно и быстро для довольно больших площадей. Несмотря на то, что вы сказали, что столбец - это все формулы, это учитывает сочетание значений и формул, таким образом, внешний цикл переходит назад через области:
Function GetLastFormulaBlank(rngInput As Excel.Range) As Excel.Range
Dim rngFormulas As Excel.Range
Dim rngArea As Excel.Range
Dim CellCounter As Long
Dim AreaCounter As Long
Dim varAreaCells As Variant
Dim rngLastFormulaBlank As Excel.Range
Set rngFormulas = rngInput.SpecialCells(xlCellTypeFormulas)
For AreaCounter = rngFormulas.Areas.Count To 1 Step -1
Set rngArea = rngFormulas.Areas(AreaCounter)
varAreaCells = rngArea.Value2
If IsArray(varAreaCells) Then
For CellCounter = UBound(varAreaCells) To LBound(varAreaCells) Step -1
If varAreaCells(CellCounter, 1) = "" Then
Set rngLastFormulaBlank = rngArea.Cells(CellCounter)
Exit For
End If
Next CellCounter
Else
If varAreaCells = "" Then
Set rngLastFormulaBlank = rngArea.Cells(1)
End If
End If
If Not rngLastFormulaBlank Is Nothing Then
Exit For
End If
Next AreaCounter
Set GetLastFormulaBlank = rngLastFormulaBlank
End Function
Вы бы назвали это следующим образом:
Sub test()
Dim rngLastFormulaBlank As Excel.Range
Set rngLastFormulaBlank = GetLastFormulaBlank(ActiveSheet.Range("A:A"))
If Not rngLastFormulaBlank Is Nothing Then
MsgBox rngLastFormulaBlank.Address
Else
MsgBox "no formulas with blanks in range"
End If
End Sub
К сожалению, эта функция недоступна в старшей версии Spark MLlib 1.5.1.
Однако вы можете найти ее в недавнем API Pipeline в Spark MLlib 2.x как RandomForestClassifier
:
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.classification.RandomForestClassifier
import org.apache.spark.ml.feature.{IndexToString, StringIndexer, VectorIndexer}
import org.apache.spark.mllib.util.MLUtils
// Load and parse the data file, converting it to a DataFrame.
val data = MLUtils.loadLibSVMFile(sc, "data/mllib/sample_libsvm_data.txt").toDF
// Index labels, adding metadata to the label column.
// Fit on whole dataset to include all labels in index.
val labelIndexer = new StringIndexer()
.setInputCol("label")
.setOutputCol("indexedLabel").fit(data)
// Automatically identify categorical features, and index them.
// Set maxCategories so features with > 4 distinct values are treated as continuous.
val featureIndexer = new VectorIndexer()
.setInputCol("features")
.setOutputCol("indexedFeatures")
.setMaxCategories(4).fit(data)
// Split the data into training and test sets (30% held out for testing)
val Array(trainingData, testData) = data.randomSplit(Array(0.7, 0.3))
// Train a RandomForest model.
val rf = new RandomForestClassifier()
.setLabelCol(labelIndexer.getOutputCol)
.setFeaturesCol(featureIndexer.getOutputCol)
.setNumTrees(10)
// Convert indexed labels back to original labels.
val labelConverter = new IndexToString()
.setInputCol("prediction")
.setOutputCol("predictedLabel")
.setLabels(labelIndexer.labels)
// Chain indexers and forest in a Pipeline
val pipeline = new Pipeline()
.setStages(Array(labelIndexer, featureIndexer, rf, labelConverter))
// Fit model. This also runs the indexers.
val model = pipeline.fit(trainingData)
// Make predictions.
val predictions = model.transform(testData)
// predictions: org.apache.spark.sql.DataFrame = [label: double, features: vector, indexedLabel: double, indexedFeatures: vector, rawPrediction: vector, probability: vector, prediction: double, predictedLabel: string]
predictions.show(10)
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// |label| features|indexedLabel| indexedFeatures|rawPrediction|probability|prediction|predictedLabel|
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// | 0.0|(692,[124,125,126...| 1.0|(692,[124,125,126...| [0.0,10.0]| [0.0,1.0]| 1.0| 0.0|
// | 0.0|(692,[124,125,126...| 1.0|(692,[124,125,126...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[129,130,131...| 1.0|(692,[129,130,131...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[154,155,156...| 1.0|(692,[154,155,156...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[154,155,156...| 1.0|(692,[154,155,156...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 0.0|(692,[181,182,183...| 1.0|(692,[181,182,183...| [1.0,9.0]| [0.1,0.9]| 1.0| 0.0|
// | 1.0|(692,[99,100,101,...| 0.0|(692,[99,100,101,...| [4.0,6.0]| [0.4,0.6]| 1.0| 0.0|
// | 1.0|(692,[123,124,125...| 0.0|(692,[123,124,125...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// | 1.0|(692,[124,125,126...| 0.0|(692,[124,125,126...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// | 1.0|(692,[125,126,127...| 0.0|(692,[125,126,127...| [10.0,0.0]| [1.0,0.0]| 0.0| 1.0|
// +-----+--------------------+------------+--------------------+-------------+-----------+----------+--------------+
// only showing top 10 rows
Примечание. Этот пример приведен в официальной документации по ML-Random классификатору леса Spark MLlib.
И вот некоторые объяснения в некоторых выходных столбцах:
predictionCol
представляет предсказанную метку. rawPredictionCol
представляет вектор длины # классов с подсчетами ярлыков обучающих экземпляров на узле дерева, который делает предсказание (доступно только для классификации). probabilityCol
представляет вероятность вектора длины # классов, равную rawPrediction
, нормированную на многокомпонентное распределение (доступно только с классификацией). Вы не можете напрямую получить вероятности классификации, но относительно легко вычислить ее самостоятельно. RandomForest - это ансамбль деревьев, и его выходная вероятность - это большинство голосов этих деревьев, деленное на общее количество деревьев.
Так как RandomForestModel в MLib дает вам обученные деревья, это легко сделать сами. Следующий код дает вероятность проблемы двоичной классификации. Его обобщение на многоклассовую классификацию прост.
def predict(points: RDD[LabeledPoint], model: RandomForestModel) = {
val numTrees = model.trees.length
val trees = points.sparkContext.broadcast(model.trees)
points.map { point =>
trees.value
.map(_.predict(point.features))
.sum / numTrees
}
}
для случая с несколькими классами вам нужно заменить карту только с помощью .map (_. pred (point.features) -> 1.0) и group by key вместо суммы и, наконец, взять максимум значений.