Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added a few map functions and tests for same. #635

Merged
merged 1 commit into from Aug 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions core/src/main/java/tech/tablesaw/api/Row.java
Expand Up @@ -52,17 +52,17 @@ private void throwWrongTypeError(String columnName) {
String actualType = tableSlice.getTable().columns().get(i).type().name();
String proposedType = columnTypeName();
throw new IllegalArgumentException(
String.format(
"Column %s is of type %s and cannot be cast to %s. Use the method for %s.",
columnName, actualType, proposedType, actualType));
String.format(
"Column %s is of type %s and cannot be cast to %s. Use the method for %s.",
columnName, actualType, proposedType, actualType));
}
}
}

private void throwColumnNotPresentError(String columnName) {
throw new IllegalStateException(
String.format(
"Column %s is not present in table %s", columnName, tableSlice.getTable().name()));
String.format(
"Column %s is not present in table %s", columnName, tableSlice.getTable().name()));
}

private String columnTypeName() {
Expand All @@ -84,7 +84,7 @@ private String columnTypeName() {
private final ColumnMap<Column<String>> stringColumnMap = new ColumnMap<>(ColumnType.STRING);
private final ColumnMap<BooleanColumn> booleanColumnMap = new ColumnMap<>(ColumnType.BOOLEAN);
private final ColumnMap<DateTimeColumn> dateTimeColumnMap =
new ColumnMap<>(ColumnType.LOCAL_DATE_TIME);
new ColumnMap<>(ColumnType.LOCAL_DATE_TIME);
private final ColumnMap<InstantColumn> instantColumnMap = new ColumnMap<>(ColumnType.INSTANT);
private final ColumnMap<TimeColumn> timeColumnMap = new ColumnMap<>(ColumnType.LOCAL_TIME);
private final ColumnMap<Column<?>> columnMap = new ColumnMap<>();
Expand Down Expand Up @@ -446,4 +446,4 @@ public String toString() {
public void setTime(String columnName, LocalTime value) {
timeColumnMap.get(columnName).set(rowNumber, value);
}
}
}
Expand Up @@ -259,6 +259,19 @@ default DoubleColumn remainder(DoubleColumn column2) {
return result;
}

default DoubleColumn remainder(double val2) {
DoubleColumn result = DoubleColumn.create(name() + " % " + val2, size());
for (int r = 0; r < size(); r++) {
double val1 = getDouble(r);
if (DoubleColumnType.isMissingValue(val1) || DoubleColumnType.isMissingValue(val2)) {
result.setMissing(r);
} else {
result.set(r, getDouble(r) % val2);
}
}
return result;
}

/** Returns the natural log of the values in this column as a NumberColumn. */
default DoubleColumn logN() {
DoubleColumn newColumn = DoubleColumn.create(name() + "[logN]", size());
Expand Down
Expand Up @@ -62,6 +62,51 @@ default StringColumn lowerCase() {
return newColumn;
}

/**
* Capitalizes each String changing the first character of each to title case as per {@link
* Character#toTitleCase(int)}, as if in a sentence. No other characters are changed.
*
* <pre>
* capitalize(null) = null
* capitalize("") = ""
* capitalize("cat") = "Cat"
* capitalize("cAt") = "CAt"
* capitalize("'cat'") = "'cat'"
* </pre>
*/
default StringColumn capitalize() {

StringColumn newColumn = StringColumn.create(name() + "[titleCase]");

for (int r = 0; r < size(); r++) {
String value = getString(r);
newColumn.append(StringUtils.capitalize(value));
}
return newColumn;
}

/**
* Repeats each the column's values elementwise, concatinating the results into a new StringColumn
*
* @param times The number of repeat desired
* <pre>
* repeat("", 2) = ""
* repeat("cat", 3) = "catcatcat"
* </pre>
*
* @return the new StringColumn
*/
default StringColumn repeat(int times) {

StringColumn newColumn = StringColumn.create(String.format("%s [rep %d]", name(), times));

for (int r = 0; r < size(); r++) {
String value = getString(r);
newColumn.append(StringUtils.repeat(value, times));
}
return newColumn;
}

default StringColumn trim() {

StringColumn newColumn = StringColumn.create(name() + "[trim]");
Expand Down Expand Up @@ -224,7 +269,7 @@ default StringColumn padStart(int minLength, char padChar) {
return newColumn;
}

default StringColumn commonPrefix(Column<?> column2) {
default StringColumn commonPrefix(Column<String> column2) {

StringColumn newColumn = StringColumn.create(name() + column2.name() + "[prefix]");

Expand All @@ -236,7 +281,7 @@ default StringColumn commonPrefix(Column<?> column2) {
return newColumn;
}

default StringColumn commonSuffix(Column<?> column2) {
default StringColumn commonSuffix(Column<String> column2) {

StringColumn newColumn = StringColumn.create(name() + column2.name() + "[suffix]");

Expand All @@ -249,7 +294,7 @@ default StringColumn commonSuffix(Column<?> column2) {
}

/** Returns a column containing the levenshtein distance between the two given string columns */
default DoubleColumn distance(Column<?> column2) {
default DoubleColumn distance(Column<String> column2) {

DoubleColumn newColumn = DoubleColumn.create(name() + column2.name() + "[distance]");

Expand All @@ -267,28 +312,47 @@ default DoubleColumn distance(Column<?> column2) {
* @param columns the column to append
* @return the new column
*/
default StringColumn join(String separator, Column<?>... columns) {
default StringColumn join(String separator, Column... columns) {
StringColumn newColumn = StringColumn.create(name() + "[column appended]", this.size());
for (int r = 0; r < size(); r++) {
String result = getString(r);
StringBuilder result = new StringBuilder(getString(r));
for (Column<?> stringColumn : columns) {
result = result + separator + stringColumn.get(r);
result.append(separator).append(stringColumn.get(r));
}
newColumn.set(r, result);
newColumn.set(r, result.toString());
}
return newColumn;
}

/**
* Return a copy of this column with the given string appended to each element
*
* @param append the string to append
* @param stringsToAppend the stringified objects to append
* @return the new column
*/
default StringColumn concatenate(Object... stringsToAppend) {
StringColumn newColumn = StringColumn.create(name() + "[append]", this.size());
for (int r = 0; r < size(); r++) {
for (Object o : stringsToAppend) {
newColumn.set(r, getString(r) + o);
}
}
return newColumn;
}

/**
* Return a copy of this column with the corresponding value of each column argument appended to
* each element. getString is used to ensure the value returned by the args are strings
*
* @param stringColumns the string columns to append
* @return the new column
*/
default StringColumn concatenate(String append) {
default StringColumn concatenate(Column... stringColumns) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this take a StringColumn or is that too specific? Otherwise maybe this should be Column<?>...

I'm getting compilation warnings on lines 315, 350, and 354 due to missing generics

StringColumn newColumn = StringColumn.create(name() + "[append]", this.size());
for (int r = 0; r < size(); r++) {
newColumn.set(r, getString(r) + append);
StringBuilder s = new StringBuilder(getString(r));
for (Column stringColumn : stringColumns) s.append(stringColumn.getString(r));
newColumn.set(r, s.toString());
}
return newColumn;
}
Expand Down
13 changes: 11 additions & 2 deletions core/src/test/java/tech/tablesaw/api/NumericColumnTest.java
@@ -1,20 +1,29 @@
package tech.tablesaw.api;

import static java.lang.Double.NaN;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import tech.tablesaw.columns.numbers.DoubleColumnType;

public class NumericColumnTest {
class NumericColumnTest {

@Test
public void testPctChange() {
void testPctChange() {
double[] data = new double[] {100, 100, 100, 100, 101, 102, 99, 98};
double missing = DoubleColumnType.missingValueIndicator();
double[] pctChange = new double[] {missing, missing, missing, missing, .01, .02, -.01, -.02};
DoubleColumn result = DoubleColumn.create("data", data).pctChange(4);
assertArrayEquals(pctChange, result.asDoubleArray(), 0.000001);
assertEquals("data 4-period Percent Change", result.name());
}

@Test
void testRemainder() {
double[] data = new double[] {100, 101, NaN, 105};
DoubleColumn result = DoubleColumn.create("data", data).remainder(20);
double[] expected = {0, 1, NaN, 5};
assertArrayEquals(expected, result.asDoubleArray());
}
}
27 changes: 27 additions & 0 deletions core/src/test/java/tech/tablesaw/api/StringColumnTest.java
Expand Up @@ -393,6 +393,33 @@ void testSubstring() {
assertEquals(result.get(2), "k");
}

@Test
void testRepeat() {
String[] words = {"running", "icecube", "back"};
StringColumn wordColumn = StringColumn.create("words", words);
StringColumn result = wordColumn.repeat(3);
assertEquals(result.get(0), "runningrunningrunning");
}

@Test
void testCapitalize() {
String[] words = {"running", "ice cube", "stuff4us"};
StringColumn wordColumn = StringColumn.create("words", words);
StringColumn result = wordColumn.capitalize();
assertEquals(result.get(0), "Running");
assertEquals(result.get(1), "Ice cube");
assertEquals(result.get(2), "Stuff4us");
}

@Test
void testConcatinate() {
String[] words = {"running", "icecube", "back"};
StringColumn wordColumn1 = StringColumn.create("words1", words);
StringColumn wordColumn2 = StringColumn.create("words2", words);
StringColumn result = wordColumn1.concatenate(wordColumn2);
assertEquals(result.get(0), "runningrunning");
}

@Test
void testSubstring2() {
String[] words = {"running", "icecube", "back"};
Expand Down