I have a list which is needed to be converted to nested lists in a list
my_list = [2,5,6,7,8,15,34,56,78]
I need list as
final_list = [[2,5,6],[7,8,15],[34,56,78]]
I wrote code using for loop with length command and range command, I know there is error with range function, but I couldn't figure it out.
my_list = [2,5,6,7,8,15,34,56,78]
max_split = 3
final_list = [[len(my_list) for _ in range(max_split)] for _ in range(max_split)]
print(final_list)
But the output I get is [[9,9,9],[9,9,9],[9,9,9]]
You can try following code
my_list = [2,5,6,7,8,15,34,56,78]
max_split = 3
final_list = [my_list[i:i + max_split ] for i in range(0, len(my_list), max_split )]
print(final_list)
Demo.
If you use the indexes returned by the for loops, you can use them to count through the indexes in your list like this:
my_list = [2,5,6,7,8,15,34,56,78]
max_split = 3
final_list = [[my_list[i+3*j] for i in range(max_split)] for j in range(max_split)]
print(final_list)
Output:
[[2, 5, 6], [7, 8, 15], [34, 56, 78]]
Related
I need to convert an array from Firebase into a List of Vector2s in Flutter for FlutterFlame.
From what I gather from the comments you have an array of integers like this:
final numbers = [1, 2, 3, 4, 5, 6, 1, 43];
You can convert this to a list of Vector2 in many ways, this is one way to do it:
final vectors = [
for(int i = 0; i < numbers.length-1; i+=2)
Vector2(numbers[i].toDouble(), numbers[i+1].toDouble())
];
I want to implement below piece of code(Java) in Dart/Flutter.
Could you please tell me how to achieve this.?
Here rows = 8, colums = not defined.
int[][] myArray = new int[8][];
Dart represents arrays in the form of List objects. A List is simply an ordered group of objects. ... Each element in the List is identified by a unique number called the index.
To get exactly what you want, you could use double List.generate, i.e.:
const cols = 31;
const rows = 12;
final array = List.generate(rows,
(i) => List.generate(cols + 1, (j) => i + j * cols + 1,
growable: false),growable: false);
array.forEach((row) {
print(row);
});
// [1, 32, 63, ...
// [2, 33, 64, ...
// [3, 34, 65, ...
// ...
There is also List.filled, where you can fill the array with some initial value when created. The following init the 2d array with 0s.
final array = List.generate(rows + 1, (i) => List.filled(cols + 1, 0,growable: false), growable: false);
I have a string with the following format:
var cadenaCoordenadas = """
1,1
1,3
4,1
5,1
1,5
1,6
2,5
0,0
"""
What I want is that each line is in the following format (in an array) to manipulate it (with Int data types as I will do operations with the new string):
[1,1]
I have the following code:
var arregloEntradas = cadenaCoordenadas.split(separator: "\n")
print("primer Arreglo: ", arregloEntradas)
for i in stride(from: 0, through:arregloEntradas.count - 1, by: 1){
let arregloEntradasFinal = arregloEntradas[i].split(separator: ",")
print(arregloEntradasFinal)
}
and I get the result of this:
this is the result
as you can see, the array elements are of string type, however I require them to be of Int type:
[1,1]
[1,3]
[4,1]
...
I hope you can help me, thank you in advance.
Here's one approach using some splitting and mapping:
var cadenaCoordenadas = """
1,1
1,3
4,1
5,1
1,5
1,6
2,5
0,0
"""
let arregloEntradasFinal = cadenaCoordenadas.split(separator: "\n")
.map { $0.split(separator: ",").compactMap { Int($0) } }
print(arregloEntradasFinal)
Output:
[[1, 1], [1, 3], [4, 1], [5, 1], [1, 5], [1, 6], [2, 5], [0, 0]]
var arregloEntradas = cadenaCoordenadas.split(separator: "\n")
print("primer Arreglo: ", arregloEntradas)
for i in stride(from: 0, through:arregloEntradas.count - 1, by: 1){
let arregloEntradasFinal = arregloEntradas[i].split(separator: ",").map { Int(String($0)) }
print(arregloEntradasFinal)
}
What you're getting in arregloEntradasFinal is correct since you're processing the string array. Later, when you want to use arregloEntradasFinal again, you should again split a string by a comma separator from arregloEntradasFinal and use the individual Int value. For example:
let index = 0 // You can also loop through the array
let values = arregloEntradasFinal[index].split(separator: ",")
let num1 = Int(values.first ?? 0) // If no value then returns 0
let num2 = Int(values.last ?? 0) // If no value then returns 0
Note - this is one of the way without using the map function.
I am using the standard (string indexer + one hot encoder + randomForest) pipeline in spark, as shown below
labelIndexer = StringIndexer(inputCol = class_label_name, outputCol="indexedLabel").fit(data)
string_feature_indexers = [
StringIndexer(inputCol=x, outputCol="int_{0}".format(x)).fit(data)
for x in char_col_toUse_names
]
onehot_encoder = [
OneHotEncoder(inputCol="int_"+x, outputCol="onehot_{0}".format(x))
for x in char_col_toUse_names
]
all_columns = num_col_toUse_names + bool_col_toUse_names + ["onehot_"+x for x in char_col_toUse_names]
assembler = VectorAssembler(inputCols=[col for col in all_columns], outputCol="features")
rf = RandomForestClassifier(labelCol="indexedLabel", featuresCol="features", numTrees=100)
labelConverter = IndexToString(inputCol="prediction", outputCol="predictedLabel", labels=labelIndexer.labels)
pipeline = Pipeline(stages=[labelIndexer] + string_feature_indexers + onehot_encoder + [assembler, rf, labelConverter])
crossval = CrossValidator(estimator=pipeline,
estimatorParamMaps=paramGrid,
evaluator=evaluator,
numFolds=3)
cvModel = crossval.fit(trainingData)
now after the the fit I can get the random forest and the feature importance using cvModel.bestModel.stages[-2].featureImportances, but this does not give me feature/ column names, rather just the feature number.
What I get is below:
print(cvModel.bestModel.stages[-2].featureImportances)
(1446,[3,4,9,18,20,103,766,981,983,1098,1121,1134,1148,1227,1288,1345,1436,1444],[0.109898803421,0.0967396441648,4.24568235244e-05,0.0369705839109,0.0163489685127,3.2286694534e-06,0.0208192703688,0.0815822887175,0.0466903663708,0.0227619959989,0.0850922269211,0.000113388896956,0.0924779490403,0.163835022713,0.118987129392,0.107373548367,3.35577640585e-05,0.000229569946193])
How can I map it back to some column names or column name + value format?
Basically to get the feature importance of random forest along with the column names.
The transformed dataset metdata has the required attributes.Here is an easy way to do -
create a pandas dataframe (generally feature list will not be huge, so no memory issues in storing a pandas DF)
pandasDF = pd.DataFrame(dataset.schema["features"].metadata["ml_attr"]
["attrs"]["binary"]+dataset.schema["features"].metadata["ml_attr"]["attrs"]["numeric"]).sort_values("idx")
Then create a broadcast dictionary to map. broadcast is necessary in a distributed environment.
feature_dict = dict(zip(pandasDF["idx"],pandasDF["name"]))
feature_dict_broad = sc.broadcast(feature_dict)
You can also look here and here
Hey why don't you just map it back to the original columns through list expansion. Here is an example:
# in your case: trainingData.columns
data_frame_columns = ["A", "B", "C", "D", "E", "F"]
# in your case: print(cvModel.bestModel.stages[-2].featureImportances)
feature_importance = (1, [1, 3, 5], [0.5, 0.5, 0.5])
rf_output = [(data_frame_columns[i], feature_importance[2][j]) for i, j in zip(feature_importance[1], range(len(feature_importance[2])))]
dict(rf_output)
{'B': 0.5, 'D': 0.5, 'F': 0.5}
I was not able to find any way to get the true initial list of the columns back after the ml algorithm, I am using this as the current workaround.
print(len(cols_now))
FEATURE_COLS=[]
for x in cols_now:
if(x[-6:]!="catVar"):
FEATURE_COLS+=[x]
else:
temp=trainingData.select([x[:-7],x[:-6]+"tmp"]).distinct().sort(x[:-6]+"tmp")
temp_list=temp.select(x[:-7]).collect()
FEATURE_COLS+=[list(x)[0] for x in temp_list]
print(len(FEATURE_COLS))
print(FEATURE_COLS)
I have kept a consistent suffix naming across all the indexer (_tmp) & encoder (_catVar) like:
column_vec_in = str_col
column_vec_out = [col+"_catVar" for col in str_col]
indexers = [StringIndexer(inputCol=x, outputCol=x+'_tmp')
for x in column_vec_in ]
encoders = [OneHotEncoder(dropLast=False, inputCol=x+"_tmp", outputCol=y)
for x,y in zip(column_vec_in, column_vec_out)]
tmp = [[i,j] for i,j in zip(indexers, encoders)]
tmp = [i for sublist in tmp for i in sublist]
This can be further improved and generalized, but currently this tedious work around works best
In my app, I have 2 arrays which are in use a lot, an array that stores score values as an Integer, and another array that stores dates in the format "mm/dd/yy". These arrays are continuously being appended, and the indexes of these arrays correspond to each other, for example, index 0 of dates array corresponds to index 0 of score array. I want these arrays to be turned into a dictionary upon when a second screen loads(these are global variables). For example, these are the type of values in each array.
score == [1,2,3,4,5,6,7,8,9]
dates == ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
What I want to happen, is that upon viewDidLoad(), this gets created.
var scoreDatesDictionary = [
"7/12/15": [1,2,3,4]
"7/13/15": [5,6,7,8]
"7/14/15": [9]
]
In its essence, the two arrays have corresponding values, (firstArray[0]) corresponds to (secondArray[0]). I am trying to make it that in the secondArray(dates), identical strings get matched up in a dictionary with their corresponding index values. I may not make much sense, but the sample code I provided should work. I spent a lot of time working with this, and I can't find a solution.
let score = [1,2,3,4,5,6,7,8,9,]
let dates = ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
var dic = [String:[Int]]()
for var index=0;index < dates.count; index++ {
let key = dates[index];
var value = dic[key]
if value == nil{
dic[key] = [score[index]]
}else{
value!.append(score[index])
dic[key] = value
}
}
println(dic)
This will log
[7/12/15: [1, 2, 3, 4], 7/14/15: [9], 7/13/15: [5, 6, 7, 8]]
func zipToDict<
S0 : SequenceType,
S1 : SequenceType where
S0.Generator.Element : Hashable
>(keys: S0, values: S1) -> [S0.Generator.Element:[S1.Generator.Element]] {
var dict: [S0.Generator.Element:[S1.Generator.Element]] = [:]
for (key, value) in zip(keys, values) {
dict[key] = (dict[key] ?? []) + [value]
}
return dict
}
let score = [1,2,3,4,5,6,7,8,9]
let dates = ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
print(zipToDict(dates, score)) // [7/12/15: [1, 2, 3, 4], 7/14/15: [9], 7/13/15: [5, 6, 7, 8]]
Working off #Leo's correct answer, here's a version that makes use of enumerate and the nil coalescing operator ?? to do this more cleanly:
For Swift 1.2:
let score = [1,2,3,4,5,6,7,8,9]
let dates = ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
var dic = [String:[Int]]()
for (index, date) in enumerate(dates) {
dic[date] = (dic[date] ?? []) + [score[index]]
}
print(dic) // prints "[7/12/15: [1, 2, 3, 4], 7/14/15: [9], 7/13/15: [5, 6, 7, 8]]"
For Swift 2.0, you need to use dates.enumerate() instead.