Skip to content

Commit 114856b

Browse files
committed
Merge branch 'master' of github.com:0xdata/h2o
2 parents 9eabaab + 87ac5a7 commit 114856b

9 files changed

+167
-48
lines changed

R/h2o-package/R/Classes.R

+89-45
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,12 @@ h2o.ddply <- function (.data, .variables, .fun = NULL, ..., .progress = 'none')
498498
if( any(bad) ) stop( sprintf('can\'t recognize .variables %s', paste(vars[bad], sep=',')) )
499499

500500
fun_name <- mm[[ '.fun' ]]
501+
502+
if(identical(as.list(substitute(.fun))[[1]], quote(`function`))) {
503+
h2o.addFunction(.data@h2o, .fun, "anonymous")
504+
fun_name <- "anonymous"
505+
}
506+
501507
exec_cmd <- sprintf('ddply(%s,c(%s),%s)', .data@key, paste(idx, collapse=','), as.character(fun_name))
502508
res <- .h2o.__exec2(.data@h2o, exec_cmd)
503509
.h2o.exec2(res$dest_key, h2o = .data@h2o, res$dest_key)
@@ -520,7 +526,7 @@ h2o.addFunction <- function(object, fun, name){
520526
if( class(name) != 'character' ) stop('name must be a name')
521527
fun_name <- name
522528
} else {
523-
fun_name <- match.call()[['fun']]
529+
fun_name <- "anonymous" #fun_name <- match.call()[['fun']]
524530
}
525531
src <- paste(deparse(fun), collapse='\n')
526532
exec_cmd <- sprintf('%s <- %s', as.character(fun_name), src)
@@ -1108,15 +1114,10 @@ head.H2OParsedData <- function(x, n = 6L, ...) {
11081114
stopifnot(length(n) == 1L)
11091115
n <- ifelse(n < 0L, max(numRows + n, 0L), min(n, numRows))
11101116
if(n == 0) return(data.frame())
1111-
1112-
x.slice = as.data.frame(x[seq_len(n),])
1113-
# if(ncol(x) > .MAX_INSPECT_COL_VIEW)
1114-
# warning(x@key, " has greater than ", .MAX_INSPECT_COL_VIEW, " columns. This may take awhile...")
1115-
# res = .h2o.__remoteSend(x@h2o, .h2o.__HACK_LEVELS2, source = x@key, max_ncols = .Machine$integer.max)
1116-
# for(i in 1:ncol(x)) {
1117-
# if(!is.null(res$levels[[i]]))
1118-
# x.slice[,i] <- factor(x.slice[,i], levels = res$levels[[i]])
1119-
# }
1117+
1118+
tmp_head <- x[seq_len(n),]
1119+
x.slice = as.data.frame(tmp_head)
1120+
h2o.rm(tmp_head@h2o, tmp_head@key)
11201121
return(x.slice)
11211122
}
11221123

@@ -1127,16 +1128,10 @@ tail.H2OParsedData <- function(x, n = 6L, ...) {
11271128
if(n == 0) return(data.frame())
11281129

11291130
idx <- seq.int(to = nrx, length.out = n)
1130-
x.slice <- as.data.frame(x[idx,])
1131+
tmp_tail <- x[idx,]
1132+
x.slice <- as.data.frame(tmp_tail)
1133+
h2o.rm(tmp_tail@h2o, tmp_tail@key)
11311134
rownames(x.slice) <- idx
1132-
1133-
# if(ncol(x) > .MAX_INSPECT_COL_VIEW)
1134-
# warning(x@key, " has greater than ", .MAX_INSPECT_COL_VIEW, " columns. This may take awhile...")
1135-
# res = .h2o.__remoteSend(x@h2o, .h2o.__HACK_LEVELS2, source = x@key, max_ncols = .Machine$integer.max)
1136-
# for(i in 1:ncol(x)) {
1137-
# if(!is.null(res$levels[[i]]))
1138-
# x.slice[,i] <- factor(x.slice[,i], levels = res$levels[[i]])
1139-
# }
11401135
return(x.slice)
11411136
}
11421137

@@ -1254,34 +1249,83 @@ screeplot.H2OPCAModel <- function(x, npcs = min(10, length(x@model$sdev)), type
12541249
as.logical(.h2o.__unop2("canBeCoercedToLogical", vec))
12551250
}
12561251

1257-
setMethod("ifelse", signature(test="H2OParsedData", yes="ANY", no="ANY"), function(test, yes, no) {
1258-
if(!(is.numeric(yes) || class(yes) == "H2OParsedData") || !(is.numeric(no) || class(no) == "H2OParsedData"))
1259-
stop("Unimplemented")
1260-
if(!test@logic && !.canBeCoercedToLogical(test)) stop(test@key, " is not a H2O logical data type")
1261-
.h2o.__multop2("ifelse", test, yes, no)
1262-
})
1263-
1264-
setMethod("ifelse", signature(test="logical", yes="H2OParsedData", no="numeric"), function(test, yes, no) {
1265-
if(length(test) > 1) stop("test must be a single logical value")
1266-
.h2o.__multop2("ifelse", as.numeric(test), yes, no)
1267-
})
1268-
1269-
setMethod("ifelse", signature(test="logical", yes="numeric", no="H2OParsedData"), function(test, yes, no) {
1270-
if(length(test) > 1) stop("test must be a single logical value")
1271-
.h2o.__multop2("ifelse", as.numeric(test), yes, no)
1272-
})
1252+
.check.ifelse.conditions <-
1253+
function(test, yes, no, type) {
1254+
if (type == "test") {
1255+
return(class(test) == "H2OParsedData"
1256+
&& (is.numeric(yes) || class(yes) == "H2OParsedData" || is.logical(yes))
1257+
&& (is.numeric(no) || class(no) == "H2OParsedData" || is.logical(no))
1258+
&& (test@logic || .canBeCoercedToLogical(test)))
1259+
}
1260+
}
12731261

1274-
setMethod("ifelse", signature(test="logical", yes="H2OParsedData", no="H2OParsedData"), function(test, yes, no) {
1275-
if(length(test) > 1) stop("test must be a single logical value")
1276-
.h2o.__multop2("ifelse", as.numeric(test), yes, no)
1277-
})
1262+
ifelse<-
1263+
function (test, yes, no)
1264+
{
1265+
if (.check.ifelse.conditions(test, yes, no, "test")) {
1266+
if (is.logical(yes)) yes <- as.numeric(yes)
1267+
if (is.logical(no)) no <- as.numeric(no)
1268+
return(.h2o.__multop2("ifelse", test, yes, no))
1269+
1270+
} else if ( class(yes) == "H2OParsedData" && class(test) == "logical") {
1271+
if (is.logical(yes)) yes <- as.numeric(yes)
1272+
if (is.logical(no)) no <- as.numeric(no)
1273+
return(.h2o.__multop2("ifelse", as.numeric(test), yes, no))
1274+
1275+
} else if (class(no) == "H2OParsedData" && class(test) == "logical") {
1276+
if (is.logical(yes)) yes <- as.numeric(yes)
1277+
if (is.logical(no)) no <- as.numeric(no)
1278+
return(.h2o.__multop2("ifelse", as.numeric(test), yes, no))
1279+
}
1280+
if (is.atomic(test))
1281+
storage.mode(test) <- "logical"
1282+
else test <- if (isS4(test))
1283+
as(test, "logical")
1284+
else as.logical(test)
1285+
ans <- test
1286+
ok <- !(nas <- is.na(test))
1287+
if (any(test[ok]))
1288+
ans[test & ok] <- rep(yes, length.out = length(ans))[test &
1289+
ok]
1290+
if (any(!test[ok]))
1291+
ans[!test & ok] <- rep(no, length.out = length(ans))[!test &
1292+
ok]
1293+
ans[nas] <- NA
1294+
ans
1295+
}
12781296

1279-
setMethod("levels", "H2OParsedData", function(x) {
1280-
# if(ncol(x) != 1) return(NULL)
1281-
if(ncol(x) != 1) stop("Can only retrieve levels of one column.")
1282-
res = .h2o.__remoteSend(x@h2o, .h2o.__HACK_LEVELS2, source = x@key, max_ncols = .Machine$integer.max)
1283-
res$levels[[1]]
1284-
})
1297+
#setMethod("ifelse", signature(test="H2OParsedData", yes="ANY", no="ANY"), function(test, yes, no) {
1298+
# if(!(is.numeric(yes) || class(yes) == "H2OParsedData") || !(is.numeric(no) || class(no) == "H2OParsedData"))
1299+
# stop("Unimplemented")
1300+
# if(!test@logic && !.canBeCoercedToLogical(test)) stop(test@key, " is not a H2O logical data type")
1301+
# h2o.exec(ifelse(test, yes, no))
1302+
## .h2o.__multop2("ifelse", eval(test), yes, no)
1303+
#})
1304+
##
1305+
#setMethod("ifelse", signature(test="logical", yes="H2OParsedData", no="ANY"), function(test, yes, no) {
1306+
# if(length(test) > 1) stop("test must be a single logical value")
1307+
# h2o.exec(ifelse(test, yes, no))
1308+
## .h2o.__multop2("ifelse", as.numeric(test), eval(yes), no)
1309+
#})
1310+
#
1311+
#setMethod("ifelse", signature(test="logical", yes="ANY", no="H2OParsedData"), function(test, yes, no) {
1312+
# if(length(test) > 1) stop("test must be a single logical value")
1313+
# h2o.exec(ifelse(test, yes, no))
1314+
## .h2o.__multop2("ifelse", as.numeric(test), yes, eval(no))
1315+
#})
1316+
#
1317+
#setMethod("ifelse", signature(test="logical", yes="H2OParsedData", no="H2OParsedData"), function(test, yes, no) {
1318+
# if(length(test) > 1) stop("test must be a single logical value")
1319+
# h2o.exec(ifelse(test, yes, no))
1320+
## .h2o.__multop2("ifelse", as.numeric(test), eval(yes), eval(no))
1321+
#})
1322+
#
1323+
#setMethod("levels", "H2OParsedData", function(x) {
1324+
# # if(ncol(x) != 1) return(NULL)
1325+
# if(ncol(x) != 1) stop("Can only retrieve levels of one column.")
1326+
# res = .h2o.__remoteSend(x@h2o, .h2o.__HACK_LEVELS2, source = x@key, max_ncols = .Machine$integer.max)
1327+
# res$levels[[1]]
1328+
#})
12851329

12861330
#----------------------------- Work in Progress -------------------------------#
12871331
# TODO: Need to change ... to environment variables and pass to substitute method,

R/tests/testdir_jira/runit_pub_486_nested_ifelse.R

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ test.nested_ifelse <- function(conn) {
88
e <- ifelse(a == b, b, ifelse(b == b, ifelse(a == d, 3.1415, 0), a))
99
print(e)
1010

11+
r.hex <- as.h2o(conn, iris[,1:4])
12+
f <- ifelse( a == 1, !c(3), 1.23)
13+
g <- ifelse( b == 0, !c(!3), 1.23 <= 2.34)
14+
15+
h2o.exec( f <- ifelse( a == 1, !c(1), 1.23))
16+
h2o.exec(g <- ifelse( b == 0, !c(!3), 1.23 <= 2.34))
17+
1118
testEnd()
1219
}
1320

R/tests/testdir_jira/runit_NOPASS_pub_532_negative_exponent.R R/tests/testdir_jira/runit_pub_532_negative_exponent.R

+17-1
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,27 @@ h2o.exec(covtype.hex$C55^2)
1414
h2o.exec(covtype.hex$C55^(-2))
1515

1616
# currently fails:
17-
h2o.exec(covtype.hex$C55^-2)
17+
val0 <- h2o.exec(covtype.hex$C55^-2)
1818
h2o.exec(covtype.hex$C55^ -2)
1919
h2o.exec(covtype.hex$C55 ^-2)
2020
h2o.exec(covtype.hex$C55 ^-2 )
2121

22+
23+
#w/o h2o.exec:
24+
val <- covtype.hex$C55^-2
25+
covtype.hex$C55^ -2
26+
covtype.hex$C55 ^-2
27+
covtype.hex$C55 ^-2
28+
29+
print(val0)
30+
31+
print("================")
32+
33+
print(val)
34+
35+
print(tail(val))
36+
37+
2238
testEnd()
2339

2440
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
setwd(normalizePath(dirname(R.utils::commandArgs(asValues=TRUE)$"f")))
2+
source('../findNSourceUtils.R')
3+
4+
test.pub_575 <- function(localH2O) {
5+
6+
covtype.hex <- h2o.importFile(localH2O, normalizePath(locate("smalldata/covtype/covtype.20k.data")), "cov")
7+
8+
hex <- covtype.hex
9+
10+
print(ifelse(TRUE, hex, hex[,1] <- hex[,1] + 1))
11+
print(h2o.exec(ifelse(1, hex, hex[,1] <- hex[,1] + 1)))
12+
13+
14+
#ensure that base ifelse is not broken
15+
print(ifelse(TRUE, iris, iris[,1] <- iris[,1] + 1))
16+
17+
testEnd()
18+
19+
}
20+
21+
doTest("PUB-575 ifelse with embedded assignment", test.pub_575)
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
setwd(normalizePath(dirname(R.utils::commandArgs(asValues=TRUE)$"f")))
2+
source('../findNSourceUtils.R')
3+
4+
test.pub.696 <- function(conn) {
5+
6+
a <- h2o.exec(a <- rep_len(0,1000000), h2o = conn)
7+
b <- h2o.exec(b <- runif(a, -1), h2o = conn)
8+
9+
d <- h2o.exec(d <- cbind(a,b), h2o = conn)
10+
11+
print(d)
12+
print(dim(d))
13+
14+
a2 <- h2o.exec(a2 <- rep_len(0,1000000000))
15+
b2 <- h2o.exec(b2 <- runif(a, -1))
16+
17+
testEnd()
18+
}
19+
20+
doTest("cbind of something created by rep_len", test.pub.696 )

src/main/java/water/exec/ASTOp.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,17 @@ public abstract class ASTOp extends AST {
161161
putPrefix(new ASTPrint ());
162162
putPrefix(new ASTLs ());
163163
}
164+
static private boolean isReserved(String fn) {
165+
return UNI_INFIX_OPS.containsKey(fn) || BIN_INFIX_OPS.containsKey(fn) || PREFIX_OPS.containsKey(fn);
166+
}
164167
static private void putUniInfix(ASTOp ast) { UNI_INFIX_OPS.put(ast.opStr(),ast); }
165168
static private void putBinInfix(ASTOp ast) { BIN_INFIX_OPS.put(ast.opStr(),ast); }
166169
static private void putPrefix (ASTOp ast) { PREFIX_OPS.put(ast.opStr(),ast); }
167-
static void putUDF (ASTOp ast, String fn) { UDF_OPS.put(fn,ast); }
170+
static void putUDF (ASTOp ast, String fn) {
171+
if (isReserved(fn)) throw new IllegalArgumentException("Trying to overload a reserved method: "+fn+". Must not overload a reserved method with a user-defined function.");
172+
if (UDF_OPS.containsKey(fn)) removeUDF(fn);
173+
UDF_OPS.put(fn,ast);
174+
}
168175
static void removeUDF (String fn) { UDF_OPS.remove(fn); }
169176
static public ASTOp isOp(String id) {
170177
// This order matters. If used as a prefix OP, `+` and `-` are binary only.
@@ -447,7 +454,7 @@ class ASTCanBeCoercedToLogical extends ASTUniPrefixOp {
447454
Vec[] v = fr.vecs();
448455
for (Vec aV : v) {
449456
if (aV.isInt()) {
450-
if (aV.min() == 0 && aV.max() == 1) {
457+
if ((aV.min() == 0 && aV.max() == 1) || (aV.min() == 0 && aV.min() == aV.max()) || (aV.min() == 1 && aV.min() == aV.max())) {
451458
d = 1;
452459
break;
453460
}

src/main/java/water/exec/Exec2.java

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ public boolean filter(H2O.KeyInfo k) {
9999
}
100100

101101
// Some global constants
102+
global.add(new ASTId(Type.DBL,"TRUE",0,global.size())); env.push(1.0);
103+
global.add(new ASTId(Type.DBL,"FALSE",0,global.size())); env.push(0.0);
102104
global.add(new ASTId(Type.DBL,"T",0,global.size())); env.push(1.0);
103105
global.add(new ASTId(Type.DBL,"F",0,global.size())); env.push(0.0);
104106
global.add(new ASTId(Type.DBL,"NA",0,global.size())); env.push(Double.NaN);
@@ -195,6 +197,7 @@ String isID() {
195197
if( isReserved(c) ) return null;
196198
// Fail on leading numeric
197199
if( isDigit(c) ) return null;
200+
if (c == '^' && _buf[_x+1] == '-') return _str.substring(++_x -1, _x);
198201
_x++; // Accept parse of 1 char
199202

200203
// If first char is letter, standard ID

0 commit comments

Comments
 (0)