/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.operator.preprocessing.filter;
import com.rapidminer.example.Attribute;
import com.rapidminer.example.AttributeRole;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.UserError;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.parameter.ParameterTypeString;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* This operator switches off all features whose name matches the one given in the parameter
* <code>skip_features_with_name</code>. The name can be defined as a regular expression.
*
* @author Buelent Moeller, Ingo Mierswa
*/
public class FeatureNameFilter extends FeatureFilter {
/**
* The parameter name for "Remove attributes with a matching name (accepts regular
* expressions)"
*/
public static final String PARAMETER_SKIP_FEATURES_WITH_NAME = "skip_features_with_name";
/**
* The parameter name for "Does not remove attributes if their name fulfills this matching
* criterion (accepts regular expressions)"
*/
public static final String PARAMETER_EXCEPT_FEATURES_WITH_NAME = "except_features_with_name";
private Pattern skipPattern;
private Pattern exceptionPattern;
public FeatureNameFilter(OperatorDescription description) {
super(description);
}
@Override
public ExampleSet apply(ExampleSet exampleSet) throws OperatorException {
// set some internal parameters as a side effect.
// TODO: Can't we do that in some init method?
String regex = getParameterAsString(PARAMETER_SKIP_FEATURES_WITH_NAME);
try {
skipPattern = Pattern.compile(regex);
} catch (PatternSyntaxException e) {
throw new UserError(this, 206, regex, e.getMessage());
}
regex = getParameterAsString(PARAMETER_EXCEPT_FEATURES_WITH_NAME);
if ((regex == null) || (regex.trim().length() == 0)) {
exceptionPattern = null;
} else {
try {
exceptionPattern = Pattern.compile(regex);
} catch (PatternSyntaxException e) {
throw new UserError(this, 206, regex, e.getMessage());
}
}
return super.apply(exampleSet);
}
/**
* Implements the method required by the superclass. For features whose name matches the input
* name (regular expression). If the input name does not match the the input name (regular
* expression) will not be switched off. If no parameter was provided, FALSE is always returned,
* so no feature is switched off.
*
* @param attributeRole
* Feature to check.
* @return TRUE if this feature should <b>not</b> be active in the output example set of this
* operator. FALSE otherwise.
*/
@Override
public boolean switchOffFeature(AttributeRole attributeRole) throws OperatorException {
Attribute attribute = attributeRole.getAttribute();
Matcher nameSkipMatcher = skipPattern.matcher(attribute.getName());
Matcher specialNameSkipMatcher = null;
if (attributeRole.isSpecial()) {
specialNameSkipMatcher = skipPattern.matcher(attributeRole.getSpecialName());
}
Matcher exceptionMatcher = exceptionPattern != null ? exceptionPattern.matcher(attribute.getName()) : null;
Matcher specialExceptionMatcher = null;
if (attributeRole.isSpecial()) {
specialExceptionMatcher = exceptionPattern != null ? exceptionPattern.matcher(attributeRole.getSpecialName())
: null;
}
return (nameSkipMatcher.matches() || ((specialNameSkipMatcher != null) && (specialNameSkipMatcher.matches())))
&& ((exceptionMatcher == null) || (!exceptionMatcher.matches()))
&& ((specialExceptionMatcher == null) || (!specialExceptionMatcher.matches()));
}
@Override
public List<ParameterType> getParameterTypes() {
List<ParameterType> types = super.getParameterTypes();
types.add(new ParameterTypeString(PARAMETER_SKIP_FEATURES_WITH_NAME,
"Remove attributes with a matching name (accepts regular expressions)", false));
types.add(new ParameterTypeString(PARAMETER_EXCEPT_FEATURES_WITH_NAME,
"Does not remove attributes if their name fulfills this matching criterion (accepts regular expressions)",
true));
return types;
}
}