Invariants: Comparing behavior with data
frames
This vignette defines invariants for subsetting and subset-assignment
for tibbles, and illustrates where their behaviour differs from data
frames. The goal is to define a small set of invariants that
consistently define how behaviors interact. Some behaviors are defined
using functions of the vctrs package, e.g. vec_slice()
,
vec_recycle()
and vec_as_index()
. Refer to
their documentation for more details about the invariants that they
follow.
The subsetting and subassignment operators for data frames and
tibbles are particularly tricky, because they support both row and
column indexes, both of which are optionally missing. We resolve this by
first defining column access with [[
and $
,
then column-wise subsetting with [
, then row-wise
subsetting, then the composition of both.
Conventions
In this article, all behaviors are demonstrated using one example
data frame and its tibble equivalent:
library(tibble)
library(vctrs)
new_df <- function() {
df <- data.frame(n = c(1L, NA, 3L, NA))
df$c <- letters[5:8]
df$li <- list(9, 10:11, 12:14, "text")
df
}
new_tbl <- function() {
as_tibble(new_df())
}
Results of the same code for data frames and tibbles are presented
side by side:
new_df()
#> n c li
#> 1 1 e 9
#> 2 NA f 10, 11
#> 3 3 g 12, 13, 14
#> 4 NA h text
|
new_tbl()
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA f <int [2]>
#> 3 3 g <int [3]>
#> 4 NA h <chr [1]>
|
If the results are identical (after converting to a data frame if
necessary), only the tibble result is shown.
Subsetting operations are read-only. The same objects are reused in
all examples:
df <- new_df()
tbl <- new_tbl()
Where needed, we also show examples with hierarchical columns
containing a data frame or a matrix:
new_tbl2 <- function() {
tibble(
tb = tbl,
m = diag(4)
)
}
new_df2 <- function() {
df2 <- new_tbl2()
class(df2) <- "data.frame"
class(df2$tb) <- "data.frame"
df2
}
df2 <- new_df2()
tbl2 <- new_tbl2()
|
|
new_tbl()
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA f <int [2]>
#> 3 3 g <int [3]>
#> 4 NA h <chr [1]>
|
For subset assignment (subassignment, for short), we need a fresh
copy of the data for each test. The with_*()
functions
(omitted here for brevity) allow for a more concise notation. These
functions take an assignment expression, execute it on a fresh copy of
the data, and return the data for printing. The first example prints
what’s really executed, further examples omit this output.
with_df(df$n <- rev(df$n), verbose = TRUE)
#> {
#> df <- new_df()
#> df$n <- rev(df$n)
#> df
#> }
#> n c li
#> 1 NA e 9
#> 2 3 f 10, 11
#> 3 NA g 12, 13, 14
#> 4 1 h text
|
with_tbl(tbl$n <- rev(tbl$n), verbose = TRUE)
#> {
#> tbl <- new_tbl()
#> tbl$n <- rev(tbl$n)
#> tbl
#> }
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 NA e <dbl [1]>
#> 2 3 f <int [2]>
#> 3 NA g <int [3]>
#> 4 1 h <chr [1]>
|
Column extraction
Definition of x[[j]]
x[[j]]
is equal to .subset2(x, j)
.
|
|
tbl[[1]]
#> [1] 1 NA 3 NA
|
|
|
.subset2(tbl, 1)
#> [1] 1 NA 3 NA
|
NB: x[[j]]
always returns an object of size
nrow(x)
if the column exists.
j
must be a single number or a string, as enforced by
.subset2(x, j)
.
|
|
tbl[[1:2]]
#> Error:
#> ! The `j` argument of
#> `[[.tbl_df` can't be a vector of
#> length 2 as of tibble 3.0.0.
#> ℹ Recursive subsetting is
#> deprecated for tibbles.
|
df[[c("n", "c")]]
#> Error in .subset2(x, i, exact = exact): subscript out of bounds
|
tbl[[c("n", "c")]]
#> Error in `tbl[[c("n", "c")]]`:
#> ! Can't extract column with `c("n", "c")`.
#> ✖ Subscript `c("n", "c")` must be size 1, not 2.
|
df[[TRUE]]
#> [1] 1 NA 3 NA
|
tbl[[TRUE]]
#> Error in `tbl[[TRUE]]`:
#> ! Can't extract column with `TRUE`.
#> ✖ `TRUE` must be numeric or character, not `TRUE`.
|
df[[mean]]
#> Error in .subset2(x, i, exact = exact): invalid subscript type 'closure'
|
tbl[[mean]]
#> Error in `tbl[[mean]]`:
#> ! Can't extract column with `mean`.
#> ✖ `mean` must be numeric or character, not a function.
|
NA
indexes, numeric out-of-bounds (OOB) values, and
non-integers throw an error:
|
|
tbl[[NA]]
#> Error in `tbl[[NA]]`:
#> ! Can't extract column with `NA`.
#> ✖ Subscript `NA` must be a location, not an integer `NA`.
|
df[[NA_character_]]
#> NULL
|
tbl[[NA_character_]]
#> Error in `tbl[[NA_character_]]`:
#> ! Can't extract column with `NA_character_`.
#> ✖ Subscript `NA_character_` must be a location, not a character `NA`.
|
df[[NA_integer_]]
#> NULL
|
tbl[[NA_integer_]]
#> Error in `tbl[[NA_integer_]]`:
#> ! Can't extract column with `NA_integer_`.
#> ✖ Subscript `NA_integer_` must be a location, not an integer `NA`.
|
df[[-1]]
#> Error in .subset2(x, i, exact = exact): invalid negative subscript in get1index <real>
|
tbl[[-1]]
#> Error in `tbl[[-1]]`:
#> ! Can't extract column with `-1`.
#> ✖ Subscript `-1` must be a positive location, not -1.
|
df[[4]]
#> Error in .subset2(x, i, exact = exact): subscript out of bounds
|
tbl[[4]]
#> Error in `tbl[[4]]`:
#> ! Can't extract columns past the end.
#> ℹ Location 4 doesn't exist.
#> ℹ There are only 3 columns.
|
df[[1.5]]
#> [1] 1 NA 3 NA
|
tbl[[1.5]]
#> Error in `tbl[[1.5]]`:
#> ! Can't extract column with `1.5`.
#> ✖ Can't convert from `j` <double> to <integer> due to loss of precision.
|
|
|
tbl[[Inf]]
#> Error in `tbl[[Inf]]`:
#> ! Can't extract column with `Inf`.
#> ✖ Can't convert from `j` <double> to <integer> due to loss of precision.
|
Character OOB access is silent because a common package idiom is to
check for the absence of a column with
is.null(df[[var]])
.
Definition of x$name
x$name
and x$"name"
are equal to
x[["name"]]
.
|
|
|
|
|
|
|
|
tbl[["n"]]
#> [1] 1 NA 3 NA
|
Unlike data frames, tibbles do not partially match names. Because
df$x
is rarely used in packages, it can raise a
warning:
df$l
#> [[1]]
#> [1] 9
#>
#> [[2]]
#> [1] 10 11
#>
#> [[3]]
#> [1] 12 13 14
#>
#> [[4]]
#> [1] "text"
|
tbl$l
#> Warning: Unknown or uninitialised
#> column: `l`.
#> NULL
|
|
|
tbl$not_present
#> Warning: Unknown or uninitialised
#> column: `not_present`.
#> NULL
|
Column subsetting
Definition of x[j]
j
is converted to an integer vector by
vec_as_index(j, ncol(x), names = names(x))
. Then
x[c(j_1, j_2, ..., j_n)]
is equivalent to
tibble(x[[j_1]], x[[j_2]], ..., x[[j_n]])
, keeping the
corresponding column names. This implies that j
must be a
numeric or character vector, or a logical vector with length 1 or
ncol(x)
.
|
|
tbl[1:2]
#> # A tibble: 4 × 2
#> n c
#> <int> <chr>
#> 1 1 e
#> 2 NA f
#> 3 3 g
#> 4 NA h
|
When subsetting repeated indexes, the resulting column names are
undefined, do not rely on them.
df[c(1, 1)]
#> n n.1
#> 1 1 1
#> 2 NA NA
#> 3 3 3
#> 4 NA NA
|
tbl[c(1, 1)]
#> # A tibble: 4 × 2
#> n n
#> <int> <int>
#> 1 1 1
#> 2 NA NA
#> 3 3 3
#> 4 NA NA
|
For tibbles with repeated column names, subsetting by name uses the
first matching column.
nrow(df[j])
equals nrow(df)
.
|
|
tbl[integer()]
#> # A tibble: 4 × 0
|
Tibbles support indexing by a logical matrix, but only if all values
in the returned vector are compatible.
df[is.na(df)]
#> [[1]]
#> [1] NA
#>
#> [[2]]
#> [1] NA
|
tbl[is.na(tbl)]
#> [1] NA NA
|
df[!is.na(df)]
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] 3
#>
#> [[3]]
#> [1] "e"
#>
#> [[4]]
#> [1] "f"
#>
#> [[5]]
#> [1] "g"
#>
#> [[6]]
#> [1] "h"
#>
#> [[7]]
#> [1] 9
#>
#> [[8]]
#> [1] 10 11
#>
#> [[9]]
#> [1] 12 13 14
#>
#> [[10]]
#> [1] "text"
|
tbl[!is.na(tbl)]
#> Error in `vec_c()` at ]8;line = 12:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subsetting-matrix.Rtibble/R/subsetting-matrix.R:12:2]8;;:
#> ! Can't combine `n` <integer> and `c` <character>.
|
Definition of x[, j]
x[, j]
is equal to x[j]
. Tibbles do not
perform column extraction if x[j]
would yield a single
column.
|
|
tbl[, 1]
#> # A tibble: 4 × 1
#> n
#> <int>
#> 1 1
#> 2 NA
#> 3 3
#> 4 NA
|
|
|
tbl[, 1:2]
#> # A tibble: 4 × 2
#> n c
#> <int> <chr>
#> 1 1 e
#> 2 NA f
#> 3 3 g
#> 4 NA h
|
Definition of x[, j, drop = TRUE]
For backward compatiblity, x[, j, drop = TRUE]
performs
column extraction, returning x[j][[1]]
when ncol(x[j])
is 1.
|
|
tbl[, 1, drop = TRUE]
#> [1] 1 NA 3 NA
|
Row subsetting
Definition of x[i, ]
x[i, ]
is equal to
tibble(vec_slice(x[[1]], i), vec_slice(x[[2]], i), ...)
.
|
|
tbl[3, ]
#> # A tibble: 1 × 3
#> n c li
#> <int> <chr> <list>
#> 1 3 g <int [3]>
|
This means that i
must be a numeric vector, or a logical
vector of length nrow(x)
or 1. For compatibility,
i
can also be a character vector containing positive
numbers.
df[mean, ]
#> Error in xj[i]: invalid subscript type 'closure'
|
tbl[mean, ]
#> Error in `tbl[mean, ]`:
#> ! Can't subset rows with `mean`.
#> ✖ `mean` must be logical, numeric, or character, not a function.
|
df[list(1), ]
#> Error in xj[i]: invalid subscript type 'list'
|
tbl[list(1), ]
#> Error in `tbl[list(1), ]`:
#> ! Can't subset rows with `list(1)`.
#> ✖ `list(1)` must be logical, numeric, or character, not a list.
|
|
|
tbl["1", ]
#> # A tibble: 1 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
|
Exception: OOB values generate warnings instead of errors:
|
|
tbl[10, ]
#> # A tibble: 1 × 3
#> n c li
#> <int> <chr> <list>
#> 1 NA <NA> <NULL>
|
|
|
tbl["x", ]
#> # A tibble: 1 × 3
#> n c li
#> <int> <chr> <list>
#> 1 NA <NA> <NULL>
|
Unlike data frames, only logical vectors of length 1 are recycled.
df[c(TRUE, FALSE), ]
#> n c li
#> 1 1 e 9
#> 3 3 g 12, 13, 14
|
tbl[c(TRUE, FALSE), ]
#> Error in `tbl[c(TRUE, FALSE), ]`:
#> ! Can't subset rows with `c(TRUE, FALSE)`.
#> ✖ Logical subscript `c(TRUE, FALSE)` must be size 1 or 4, not 2.
|
NB: scalar logicals are recycled, but scalar numerics are not. That
makes the x[NA, ]
and x[NA_integer_, ]
return
different results.
|
|
tbl[NA, ]
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 NA <NA> <NULL>
#> 2 NA <NA> <NULL>
#> 3 NA <NA> <NULL>
#> 4 NA <NA> <NULL>
|
|
|
tbl[NA_integer_, ]
#> # A tibble: 1 × 3
#> n c li
#> <int> <chr> <list>
#> 1 NA <NA> <NULL>
|
Definition of x[i, , drop = TRUE]
drop = TRUE
has no effect when not selecting a single
row:
df[1, , drop = TRUE]
#> $n
#> [1] 1
#>
#> $c
#> [1] "e"
#>
#> $li
#> $li[[1]]
#> [1] 9
|
tbl[1, , drop = TRUE]
#> # A tibble: 1 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
|
Row and column subsetting
Definition of x[]
and x[,]
x[]
and x[,]
are equivalent to
x
.
Definition of x[i, j]
x[i, j]
is equal to x[i, ][j]
.
Definition of x[[i, j]]
i
must be a numeric vector of length 1.
x[[i, j]]
is equal to x[i, ][[j]]
, or
vctrs::vec_slice(x[[j]], i)
.
df[[1, 1]]
#> [1] 1
df[[1, 3]]
#> [1] 9
This implies that j
must be a numeric or character
vector of length 1.
NB: vec_size(x[[i, j]])
always equals 1. Unlike
x[i, ]
, x[[i, ]]
is not valid.
Column update
Definition of x[[j]] <- a
If a
is a vector then x[[j]] <- a
replaces the j
th column with value a
.
a
is recycled to the same size as x
so must
have size nrow(x)
or 1. (The only exception is when
a
is NULL
, as described below.) Recycling also
works for list, data frame, and matrix columns.
|
|
with_tbl(tbl[["li"]] <- list(0))
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA f <dbl [1]>
#> 3 3 g <dbl [1]>
#> 4 NA h <dbl [1]>
|
with_df2(df2[["tb"]] <- df[1, ])
#> Error in `[[<-.data.frame`(`*tmp*`, "tb", value = structure(list(n = 1L, : replacement has 1 row, data has 4
|
with_tbl2(tbl2[["tb"]] <- tbl[1, ])
#> # A tibble: 4 × 2
#> tb$n $c $li m[,1] [,2]
#> <int> <chr> <list> <dbl> <dbl>
#> 1 1 e <dbl [1]> 1 0
#> 2 1 e <dbl [1]> 0 1
#> 3 1 e <dbl [1]> 0 0
#> 4 1 e <dbl [1]> 0 0
#> # … with 1 more variable:
#> # m[3:4] <dbl>
|
with_df2(df2[["m"]] <- df2[["m"]][1, , drop = FALSE])
#> Error in `[[<-.data.frame`(`*tmp*`, "m", value = structure(c(1, 0, 0, : replacement has 1 row, data has 4
|
with_tbl2(tbl2[["m"]] <- tbl2[["m"]][1, , drop = FALSE])
#> # A tibble: 4 × 2
#> tb$n $c $li m[,1] [,2]
#> <int> <chr> <list> <dbl> <dbl>
#> 1 1 e <dbl [1]> 1 0
#> 2 NA f <int [2]> 1 0
#> 3 3 g <int [3]> 1 0
#> 4 NA h <chr [1]> 1 0
#> # … with 1 more variable:
#> # m[3:4] <dbl>
|
j
must be a scalar numeric or a string, and cannot be
NA
. If j
is OOB, a new column is added on the
right hand side, with name repair if needed.
|
|
with_tbl(tbl[["x"]] <- 0)
#> # A tibble: 4 × 4
#> n c li x
#> <int> <chr> <list> <dbl>
#> 1 1 e <dbl [1]> 0
#> 2 NA f <int [2]> 0
#> 3 3 g <int [3]> 0
#> 4 NA h <chr [1]> 0
|
with_df(df[[4]] <- 0)
#> n c li V4
#> 1 1 e 9 0
#> 2 NA f 10, 11 0
#> 3 3 g 12, 13, 14 0
#> 4 NA h text 0
|
with_tbl(tbl[[4]] <- 0)
#> # A tibble: 4 × 4
#> n c li ...4
#> <int> <chr> <list> <dbl>
#> 1 1 e <dbl [1]> 0
#> 2 NA f <int [2]> 0
#> 3 3 g <int [3]> 0
#> 4 NA h <chr [1]> 0
|
with_df(df[[5]] <- 0)
#> Warning in format.data.frame(if
#> (omit) x[seq_len(n0), , drop =
#> FALSE] else x, : corrupt data
#> frame: columns will be truncated or
#> padded with NAs
#> n c li V5
#> 1 1 e 9 NULL 0
#> 2 NA f 10, 11 <NA> 0
#> 3 3 g 12, 13, 14 <NA> 0
#> 4 NA h text <NA> 0
|
with_tbl(tbl[[5]] <- 0)
#> Error in `[[<-`:
#> ! Can't assign to columns beyond the end with non-consecutive locations.
#> ℹ Input has size 3.
#> ✖ Subscript `5` contains non-consecutive location 5.
|
df[[j]] <- a
replaces the complete column so can
change the type.
[[<-
supports removing a column by assigning
NULL
to it.
Removing a nonexistent column is a no-op.
Definition of x$name <- a
x$name <- a
and x$"name" <- a
are
equivalent to x[["name"]] <- a
.
|
|
with_tbl(tbl$n <- 0)
#> # A tibble: 4 × 3
#> n c li
#> <dbl> <chr> <list>
#> 1 0 e <dbl [1]>
#> 2 0 f <int [2]>
#> 3 0 g <int [3]>
#> 4 0 h <chr [1]>
|
|
|
with_tbl(tbl[["n"]] <- 0)
#> # A tibble: 4 × 3
#> n c li
#> <dbl> <chr> <list>
#> 1 0 e <dbl [1]>
#> 2 0 f <int [2]>
#> 3 0 g <int [3]>
#> 4 0 h <chr [1]>
|
$<-
does not perform partial matching.
|
|
with_tbl(tbl$l <- 0)
#> # A tibble: 4 × 4
#> n c li l
#> <int> <chr> <list> <dbl>
#> 1 1 e <dbl [1]> 0
#> 2 NA f <int [2]> 0
#> 3 3 g <int [3]> 0
#> 4 NA h <chr [1]> 0
|
|
|
with_tbl(tbl[["l"]] <- 0)
#> # A tibble: 4 × 4
#> n c li l
#> <int> <chr> <list> <dbl>
#> 1 1 e <dbl [1]> 0
#> 2 NA f <int [2]> 0
#> 3 3 g <int [3]> 0
#> 4 NA h <chr [1]> 0
|
Column subassignment: x[j] <- a
- If
j
is missing, it’s replaced with
seq_along(x)
- If
j
is logical vector, it’s converted to numeric with
seq_along(x)[j]
.
a
is a list or data frame
If inherits(a, "list")
or
inherits(a, "data.frame")
is TRUE
, then
x[j] <- a
is equivalent to
x[[j[[1]]] <- a[[1]]
,
x[[j[[2]]]] <- a[[2]]
, …
|
|
with_tbl(tbl[1:2] <- list("x", 4:1))
#> # A tibble: 4 × 3
#> n c li
#> <chr> <int> <list>
#> 1 x 4 <dbl [1]>
#> 2 x 3 <int [2]>
#> 3 x 2 <int [3]>
#> 4 x 1 <chr [1]>
|
|
|
with_tbl(tbl[c("li", "x", "c")] <- list("x", 4:1, NULL))
#> # A tibble: 4 × 3
#> n li x
#> <int> <chr> <int>
#> 1 1 x 4
#> 2 NA x 3
#> 3 3 x 2
#> 4 NA x 1
|
If length(a)
equals 1, then it is recycled to the same
length as j
.
|
|
with_tbl(tbl[1:2] <- list(1))
#> # A tibble: 4 × 3
#> n c li
#> <dbl> <dbl> <list>
#> 1 1 1 <dbl [1]>
#> 2 1 1 <int [2]>
#> 3 1 1 <int [3]>
#> 4 1 1 <chr [1]>
|
with_df(df[1:2] <- list(0, 0, 0))
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 1:2,
#> value = list(0, 0, 0)): provided 3
#> variables to replace 2 variables
#> n c li
#> 1 0 0 9
#> 2 0 0 10, 11
#> 3 0 0 12, 13, 14
#> 4 0 0 text
|
with_tbl(tbl[1:2] <- list(0, 0, 0))
#> Error in `[<-`:
#> ! Can't recycle `list(0, 0, 0)` (size 3) to size 2.
|
with_df(df[1:3] <- list(0, 0))
#> n c li
#> 1 0 0 0
#> 2 0 0 0
#> 3 0 0 0
#> 4 0 0 0
|
with_tbl(tbl[1:3] <- list(0, 0))
#> Error in `[<-`:
#> ! Can't recycle `list(0, 0)` (size 2) to size 3.
|
An attempt to update the same column twice gives an error.
with_df(df[c(1, 1)] <- list(1, 2))
#> Error in `[<-.data.frame`(`*tmp*`, c(1, 1), value = list(1, 2)): duplicate subscripts for columns
|
with_tbl(tbl[c(1, 1)] <- list(1, 2))
#> Error in `[<-`:
#> ! Column index 1 is used
#> more than once for assignment.
|
If a
contains NULL
values, the
corresponding columns are removed after updating (i.e. position
indexes refer to columns before any modifications).
|
|
with_tbl(tbl[1:2] <- list(NULL, 4:1))
#> # A tibble: 4 × 2
#> c li
#> <int> <list>
#> 1 4 <dbl [1]>
#> 2 3 <int [2]>
#> 3 2 <int [3]>
#> 4 1 <chr [1]>
|
NA
indexes are not supported.
Just like column updates, [<-
supports changing the
type of an existing column.
Appending columns at the end (without gaps) is supported. The name of
new columns is determined by the LHS, the RHS, or by name repair (in
that order of precedence).
|
|
with_tbl(tbl[c("x", "y")] <- tibble("x", x = 4:1))
#> # A tibble: 4 × 5
#> n c li x y
#> <int> <chr> <list> <chr> <int>
#> 1 1 e <dbl [1]> x 4
#> 2 NA f <int [2]> x 3
#> 3 3 g <int [3]> x 2
#> 4 NA h <chr [1]> x 1
|
|
|
with_tbl(tbl[3:4] <- list("x", x = 4:1))
#> # A tibble: 4 × 4
#> n c li x
#> <int> <chr> <chr> <int>
#> 1 1 e x 4
#> 2 NA f x 3
#> 3 3 g x 2
#> 4 NA h x 1
|
with_df(df[4] <- list(4:1))
#> n c li V4
#> 1 1 e 9 4
#> 2 NA f 10, 11 3
#> 3 3 g 12, 13, 14 2
#> 4 NA h text 1
|
with_tbl(tbl[4] <- list(4:1))
#> # A tibble: 4 × 4
#> n c li ...4
#> <int> <chr> <list> <int>
#> 1 1 e <dbl [1]> 4
#> 2 NA f <int [2]> 3
#> 3 3 g <int [3]> 2
#> 4 NA h <chr [1]> 1
|
with_df(df[5] <- list(4:1))
#> Error in `[<-.data.frame`(`*tmp*`, 5, value = list(4:1)): new columns would leave holes after existing columns
|
with_tbl(tbl[5] <- list(4:1))
#> Error in `[<-`:
#> ! Can't assign to columns beyond the end with non-consecutive locations.
#> ℹ Input has size 3.
#> ✖ Subscript `5` contains non-consecutive location 5.
|
Tibbles support indexing by a logical matrix, but only for a scalar
RHS, and if all columns updated are compatible with the value
assigned.
with_df(df[is.na(df)] <- 4)
#> n c li
#> 1 1 e 9
#> 2 4 f 10, 11
#> 3 3 g 12, 13, 14
#> 4 4 h text
|
with_tbl(tbl[is.na(tbl)] <- 4)
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 4 f <int [2]>
#> 3 3 g <int [3]>
#> 4 4 h <chr [1]>
|
with_df(df[is.na(df)] <- 1:2)
#> n c li
#> 1 1 e 9
#> 2 1 f 10, 11
#> 3 3 g 12, 13, 14
#> 4 2 h text
|
with_tbl(tbl[is.na(tbl)] <- 1:2)
#> Error in `[<-`:
#> ! Subscript `is.na(tbl)` is
#> a matrix, the data `1:2` must
#> have size 1.
|
with_df(df[matrix(c(rep(TRUE, 5), rep(FALSE, 7)), ncol = 3)] <- 4)
#> n c li
#> 1 4 4 9
#> 2 4 f 10, 11
#> 3 4 g 12, 13, 14
#> 4 4 h text
|
with_tbl(tbl[matrix(c(rep(TRUE, 5), rep(FALSE, 7)), ncol = 3)] <- 4)
#> Error in `[<-`:
#> ! Assigned data `4` must be
#> compatible with existing data.
#> ℹ Error occurred for column `c`.
#> Caused by error in `vec_assign()` at ]8;line = 193:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:193:2]8;;:
#> ! Can't convert <double> to <character>.
|
a
is a matrix or array
If is.matrix(a)
, then a
is coerced to a
data frame with as.data.frame()
before assigning. If rows
are assigned, the matrix type must be compatible with all columns. If
is.array(a)
and any(dim(a)[-1:-2] != 1)
, an
error is thrown.
|
|
with_tbl(tbl[1:2] <- matrix(8:1, ncol = 2))
#> # A tibble: 4 × 3
#> n c li
#> <int> <int> <list>
#> 1 8 4 <dbl [1]>
#> 2 7 3 <int [2]>
#> 3 6 2 <int [3]>
#> 4 5 1 <chr [1]>
|
with_df(df[1:3, 1:2] <- matrix(6:1, ncol = 2))
#> n c li
#> 1 6 3 9
#> 2 5 2 10, 11
#> 3 4 1 12, 13, 14
#> 4 NA h text
|
with_tbl(tbl[1:3, 1:2] <- matrix(6:1, ncol = 2))
#> Error in `[<-`:
#> ! Assigned data `matrix(6:1,
#> ncol = 2)` must be compatible
#> with existing data.
#> ℹ Error occurred for column `c`.
#> Caused by error in `vec_assign()` at ]8;line = 193:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:193:2]8;;:
#> ! Can't convert <integer> to <character>.
|
|
|
with_tbl(tbl[1:2] <- array(4:1, dim = c(4, 1, 1)))
#> # A tibble: 4 × 3
#> n c li
#> <int> <int> <list>
#> 1 4 4 <dbl [1]>
#> 2 3 3 <int [2]>
#> 3 2 2 <int [3]>
#> 4 1 1 <chr [1]>
|
|
|
with_tbl(tbl[1:2] <- array(8:1, dim = c(4, 2, 1)))
#> # A tibble: 4 × 3
#> n c li
#> <int> <int> <list>
#> 1 8 4 <dbl [1]>
#> 2 7 3 <int [2]>
#> 3 6 2 <int [3]>
#> 4 5 1 <chr [1]>
|
with_df(df[1:2] <- array(8:1, dim = c(2, 1, 4)))
#> n c li
#> 1 8 4 9
#> 2 7 3 10, 11
#> 3 6 2 12, 13, 14
#> 4 5 1 text
|
with_tbl(tbl[1:2] <- array(8:1, dim = c(2, 1, 4)))
#> Error in `[<-`:
#> ! `array(8:1, dim = c(2, 1,
#> 4))` must be a vector, a bare
#> list, a data frame, a matrix, or
#> NULL.
|
with_df(df[1:2] <- array(8:1, dim = c(4, 1, 2)))
#> n c li
#> 1 8 4 9
#> 2 7 3 10, 11
#> 3 6 2 12, 13, 14
#> 4 5 1 text
|
with_tbl(tbl[1:2] <- array(8:1, dim = c(4, 1, 2)))
#> Error in `[<-`:
#> ! `array(8:1, dim = c(4, 1,
#> 2))` must be a vector, a bare
#> list, a data frame, a matrix, or
#> NULL.
|
a
is another type of vector
If vec_is(a)
, then x[j] <- a
is
equivalent to x[j] <- list(a)
. This is primarily
provided for backward compatibility.
|
|
with_tbl(tbl[1] <- 0)
#> # A tibble: 4 × 3
#> n c li
#> <dbl> <chr> <list>
#> 1 0 e <dbl [1]>
#> 2 0 f <int [2]>
#> 3 0 g <int [3]>
#> 4 0 h <chr [1]>
|
|
|
with_tbl(tbl[1] <- list(0))
#> # A tibble: 4 × 3
#> n c li
#> <dbl> <chr> <list>
#> 1 0 e <dbl [1]>
#> 2 0 f <int [2]>
#> 3 0 g <int [3]>
#> 4 0 h <chr [1]>
|
Matrices must be wrapped in list()
before assignment to
create a matrix column.
|
|
with_tbl(tbl[1] <- list(matrix(1:8, ncol = 2)))
#> # A tibble: 4 × 3
#> n[,1] [,2] c li
#> <int> <int> <chr> <list>
#> 1 1 5 e <dbl [1]>
#> 2 2 6 f <int [2]>
#> 3 3 7 g <int [3]>
#> 4 4 8 h <chr [1]>
|
|
|
|
|
|
with_tbl(tbl[1:2] <- list(matrix(1:8, ncol = 2)))
#> # A tibble: 4 × 3
#> n[,1] [,2] c[,1] [,2] li
#> <int> <int> <int> <int> <list>
#> 1 1 5 1 5 <dbl [1]>
#> 2 2 6 2 6 <int [2]>
#> 3 3 7 3 7 <int [3]>
#> 4 4 8 4 8 <chr [1]>
|
a
is NULL
Entire columns can be removed. Specifying i
is an
error.
|
|
with_tbl(tbl[1] <- NULL)
#> # A tibble: 4 × 2
#> c li
#> <chr> <list>
#> 1 e <dbl [1]>
#> 2 f <int [2]>
#> 3 g <int [3]>
#> 4 h <chr [1]>
|
|
|
with_tbl(tbl[, 2:3] <- NULL)
#> # A tibble: 4 × 1
#> n
#> <int>
#> 1 1
#> 2 NA
#> 3 3
#> 4 NA
|
with_df(df[1, 2:3] <- NULL)
#> Error in x[[jj]][iseq] <- vjj: replacement has length zero
|
with_tbl(tbl[1, 2:3] <- NULL)
#> Error in `[<-`:
#> ! `NULL` must be a vector, a
#> bare list, a data frame or a
#> matrix.
|
a
is not a vector
Any other type for a
is an error. Note that if
is.list(a)
is TRUE
, but
inherits(a, "list")
is FALSE
, then
a
is considered to be a scalar. See ?vec_is
and ?vec_proxy
for details.
with_df(df[1] <- mean)
#> Error in rep(value, length.out = n): attempt to replicate an object of type 'closure'
|
with_tbl(tbl[1] <- mean)
#> Error in `[<-`:
#> ! `mean` must be a vector, a
#> bare list, a data frame, a
#> matrix, or NULL.
|
with_df(df[1] <- lm(mpg ~ wt, data = mtcars))
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 1, value
#> = structure(list(coefficients =
#> c(`(Intercept)` = 37.285126167342,
#> : replacement element 2 has 32 rows
#> to replace 4 rows
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 1, value
#> = structure(list(coefficients =
#> c(`(Intercept)` = 37.285126167342,
#> : replacement element 3 has 32 rows
#> to replace 4 rows
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 1, value
#> = structure(list(coefficients =
#> c(`(Intercept)` = 37.285126167342,
#> : replacement element 5 has 32 rows
#> to replace 4 rows
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 1, value
#> = structure(list(coefficients =
#> c(`(Intercept)` = 37.285126167342,
#> : replacement element 7 has 5 rows
#> to replace 4 rows
#> Error in `[<-.data.frame`(`*tmp*`, 1, value = structure(list(coefficients = c(`(Intercept)` = 37.285126167342, : replacement element 10 has 3 rows, need 4
|
with_tbl(tbl[1] <- lm(mpg ~ wt, data = mtcars))
#> Error in `[<-`:
#> ! `lm(mpg ~ wt, data =
#> mtcars)` must be a vector, a bare
#> list, a data frame, a matrix, or
#> NULL.
|
Row subassignment: x[i, ] <- list(...)
x[i, ] <- a
is the same as
vec_slice(x[[j_1]], i) <- a[[1]]
,
vec_slice(x[[j_2]], i) <- a[[2]]
, … .
|
|
with_tbl(tbl[2:3, ] <- tbl[1, ])
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 1 e <dbl [1]>
#> 3 1 e <dbl [1]>
#> 4 NA h <chr [1]>
|
|
|
with_tbl(tbl[c(FALSE, TRUE, TRUE, FALSE), ] <- tbl[1, ])
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 1 e <dbl [1]>
#> 3 1 e <dbl [1]>
#> 4 NA h <chr [1]>
|
Only values of size one can be recycled.
|
|
with_tbl(tbl[2:3, ] <- tbl[1, ])
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 1 e <dbl [1]>
#> 3 1 e <dbl [1]>
#> 4 NA h <chr [1]>
|
|
|
with_tbl(tbl[2:3, ] <- list(tbl$n[1], tbl$c[1:2], tbl$li[1]))
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 1 e <dbl [1]>
#> 3 1 f <dbl [1]>
#> 4 NA h <chr [1]>
|
with_df(df[2:4, ] <- df[1:2, ])
#> Error in `[<-.data.frame`(`*tmp*`, 2:4, , value = structure(list(n = c(1L, : replacement element 1 has 2 rows, need 3
|
with_tbl(tbl[2:4, ] <- tbl[1:2, ])
#> Error in `[<-`:
#> ! Assigned data `tbl[1:2, ]`
#> must be compatible with row
#> subscript `2:4`.
#> ✖ 3 rows must be assigned.
#> ✖ Element 1 of assigned data has 2
#> rows.
#> ℹ Only vectors of size 1 are
#> recycled.
#> Caused by error in `vectbl_recycle_rhs_rows()` at ]8;line = 169:col = 6;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:169:6]8;;:
#> ! Can't recycle input of size 2 to size 3.
|
For compatibility, only a warning is issued for indexing beyond the
number of rows. Appending rows right at the end of the existing data is
supported, without warning.
|
|
with_tbl(tbl[5, ] <- tbl[1, ])
#> # A tibble: 5 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA f <int [2]>
#> 3 3 g <int [3]>
#> 4 NA h <chr [1]>
#> 5 1 e <dbl [1]>
|
|
|
with_tbl(tbl[5:7, ] <- tbl[1, ])
#> # A tibble: 7 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA f <int [2]>
#> 3 3 g <int [3]>
#> 4 NA h <chr [1]>
#> 5 1 e <dbl [1]>
#> 6 1 e <dbl [1]>
#> 7 1 e <dbl [1]>
|
with_df(df[6, ] <- df[1, ])
#> n c li
#> 1 1 e 9
#> 2 NA f 10, 11
#> 3 3 g 12, 13, 14
#> 4 NA h text
#> 5 NA <NA> NULL
#> 6 1 e 9
|
with_tbl(tbl[6, ] <- tbl[1, ])
#> Error in `[<-`:
#> ! Can't assign to rows beyond the end with non-consecutive locations.
#> ℹ Input has size 4.
#> ✖ Subscript `6` contains non-consecutive location 6.
|
with_df(df[-5, ] <- df[1, ])
#> n c li
#> 1 1 e 9
#> 2 1 e 9
#> 3 1 e 9
#> 4 1 e 9
|
with_tbl(tbl[-5, ] <- tbl[1, ])
#> Error in `[<-`:
#> ! Can't negate rows past the end.
#> ℹ Location 5 doesn't exist.
#> ℹ There are only 4 rows.
|
with_df(df[-(5:7), ] <- df[1, ])
#> n c li
#> 1 1 e 9
#> 2 1 e 9
#> 3 1 e 9
#> 4 1 e 9
|
with_tbl(tbl[-(5:7), ] <- tbl[1, ])
#> Error in `[<-`:
#> ! Can't negate rows past the end.
#> ℹ Locations 5, 6, and 7
#> don't exist.
#> ℹ There are only 4 rows.
|
with_df(df[-6, ] <- df[1, ])
#> n c li
#> 1 1 e 9
#> 2 1 e 9
#> 3 1 e 9
#> 4 1 e 9
|
with_tbl(tbl[-6, ] <- tbl[1, ])
#> Error in `[<-`:
#> ! Can't negate rows past the end.
#> ℹ Location 6 doesn't exist.
#> ℹ There are only 4 rows.
|
For compatibility, i
can also be a character vector
containing positive numbers.
|
|
with_tbl(tbl[as.character(1:3), ] <- tbl[1, ])
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 1 e <dbl [1]>
#> 3 1 e <dbl [1]>
#> 4 NA h <chr [1]>
|
Row and column subassignment
Definition of x[i, j] <- a
x[i, j] <- a
is equivalent to
x[i, ][j] <- a
.
Subassignment to x[i, j]
is stricter for tibbles than
for data frames. x[i, j] <- a
can’t change the data type
of existing columns.
with_df(df[2:3, 1] <- df[1:2, 2])
#> n c li
#> 1 1 e 9
#> 2 e f 10, 11
#> 3 f g 12, 13, 14
#> 4 <NA> h text
|
with_tbl(tbl[2:3, 1] <- tbl[1:2, 2])
#> Error in `[<-`:
#> ! Assigned data `tbl[1:2,
#> 2]` must be compatible with
#> existing data.
#> ℹ Error occurred for column `n`.
#> Caused by error in `vec_assign()` at ]8;line = 193:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:193:2]8;;:
#> ! Can't convert <character> to <integer>.
|
with_df(df[2:3, 2] <- df[1:2, 3])
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 2:3, 2,
#> value = list(9, 10:11)): provided 2
#> variables to replace 1 variables
#> n c li
#> 1 1 e 9
#> 2 NA 9 10, 11
#> 3 3 9 12, 13, 14
#> 4 NA h text
|
with_tbl(tbl[2:3, 2] <- tbl[1:2, 3])
#> Error in `[<-`:
#> ! Assigned data `tbl[1:2,
#> 3]` must be compatible with
#> existing data.
#> ℹ Error occurred for column `c`.
#> Caused by error in `vec_assign()` at ]8;line = 193:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:193:2]8;;:
#> ! Can't convert <list> to <character>.
|
with_df(df[2:3, 3] <- df2[1:2, 1])
#> Warning in
#> `[<-.data.frame`(`*tmp*`, 2:3, 3,
#> value = structure(list(n = c(1L, :
#> provided 3 variables to replace 1
#> variables
#> n c li
#> 1 1 e 9
#> 2 NA f 1
#> 3 3 g NA
#> 4 NA h text
|
with_tbl(tbl[2:3, 3] <- tbl2[1:2, 1])
#> Error in `[<-`:
#> ! Assigned data `tbl2[1:2,
#> 1]` must be compatible with
#> existing data.
#> ℹ Error occurred for column `li`.
#> Caused by error in `vec_assign()` at ]8;line = 193:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:193:2]8;;:
#> ! Can't convert <tbl_df> to <list>.
|
with_df2(df2[2:3, 1] <- df2[1:2, 2])
#> Warning in matrix(value, n, p):
#> data length [8] is not a
#> sub-multiple or multiple of the
#> number of columns [3]
#> tb.n tb.c tb.li m.1 m.2 m.3 m.4
#> 1 1 e 9 1 0 0 0
#> 2 1 0 0 0 1 0 0
#> 3 0 1 0 0 0 1 0
#> 4 NA h text 0 0 0 1
|
with_tbl2(tbl2[2:3, 1] <- tbl2[1:2, 2])
#> Error in `[<-`:
#> ! Assigned data `tbl2[1:2,
#> 2]` must be compatible with
#> existing data.
#> ℹ Error occurred for column `tb`.
#> Caused by error in `vec_assign()` at ]8;line = 193:col = 2;file:///private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpECx3vm/Rbuild51ca1b126fa/tibble/R/subassign-backend.Rtibble/R/subassign-backend.R:193:2]8;;:
#> ! Can't convert <double[,4]> to <tbl_df>.
|
|
|
with_tbl2(tbl2[2:3, 2] <- tbl[1:2, 1])
#> # A tibble: 4 × 2
#> tb$n $c $li m[,1] [,2]
#> <int> <chr> <list> <dbl> <dbl>
#> 1 1 e <dbl [1]> 1 0
#> 2 NA f <int [2]> 1 1
#> 3 3 g <int [3]> NA NA
#> 4 NA h <chr [1]> 0 0
#> # … with 1 more variable:
#> # m[3:4] <dbl>
|
A notable exception is the population of a column full of
NA
(which is of type logical
), or the use of
NA
on the right-hand side of the assignment.
|
|
with_tbl({tbl$x <- NA; tbl[2:3, "x"] <- 3:2})
#> # A tibble: 4 × 4
#> n c li x
#> <int> <chr> <list> <int>
#> 1 1 e <dbl [1]> NA
#> 2 NA f <int [2]> 3
#> 3 3 g <int [3]> 2
#> 4 NA h <chr [1]> NA
|
with_df({df[2:3, 2:3] <- NA})
#> n c li
#> 1 1 e 9
#> 2 NA <NA> NA
#> 3 3 <NA> NA
#> 4 NA h text
|
with_tbl({tbl[2:3, 2:3] <- NA})
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA <NA> <NULL>
#> 3 3 <NA> <NULL>
#> 4 NA h <chr [1]>
|
For programming, it is always safer (and faster) to use the correct
type of NA
to initialize columns.
|
|
with_tbl({tbl$x <- NA_integer_; tbl[2:3, "x"] <- 3:2})
#> # A tibble: 4 × 4
#> n c li x
#> <int> <chr> <list> <int>
#> 1 1 e <dbl [1]> NA
#> 2 NA f <int [2]> 3
#> 3 3 g <int [3]> 2
#> 4 NA h <chr [1]> NA
|
For new columns, x[i, j] <- a
fills the unassigned
rows with NA
.
with_df(df[2:3, "n"] <- 1)
#> n c li
#> 1 1 e 9
#> 2 1 f 10, 11
#> 3 1 g 12, 13, 14
#> 4 NA h text
|
with_tbl(tbl[2:3, "n"] <- 1)
#> # A tibble: 4 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 1 f <int [2]>
#> 3 1 g <int [3]>
#> 4 NA h <chr [1]>
|
|
|
with_tbl(tbl[2:3, "x"] <- 1)
#> # A tibble: 4 × 4
#> n c li x
#> <int> <chr> <list> <dbl>
#> 1 1 e <dbl [1]> NA
#> 2 NA f <int [2]> 1
#> 3 3 g <int [3]> 1
#> 4 NA h <chr [1]> NA
|
with_df(df[2:3, "n"] <- NULL)
#> Error in x[[jj]][iseq] <- vjj: replacement has length zero
|
with_tbl(tbl[2:3, "n"] <- NULL)
#> Error in `[<-`:
#> ! `NULL` must be a vector, a
#> bare list, a data frame or a
#> matrix.
|
Likewise, for new rows, x[i, j] <- a
fills the
unassigned columns with NA
.
|
|
with_tbl(tbl[5, "n"] <- list(0L))
#> # A tibble: 5 × 3
#> n c li
#> <int> <chr> <list>
#> 1 1 e <dbl [1]>
#> 2 NA f <int [2]>
#> 3 3 g <int [3]>
#> 4 NA h <chr [1]>
#> 5 0 <NA> <NULL>
|
Definition of x[[i, j]] <- a
i
must be a numeric vector of length 1.
x[[i, j]] <- a
is equivalent to
x[i, ][[j]] <- a
.
NB: vec_size(a)
must equal 1. Unlike
x[i, ] <-
, x[[i, ]] <-
is not valid.


Unit 2, Week 4 Cultural Blogpost
Issues in the Tech World
Monday January 19, 2015
In today's blogpost I am going to discuss a problem in the tech world that interests me. One of the biggest challenges facing the tech industry is how the growth in demand for content greatly exceeds the current bandwidth supply. This is particularly true for rich media like video streaming. According to a Sandvine study for the first half of 2014, Netflix and YouTube services alone accounted for almost half of all data usage:
Streaming a video or audio file consists of viewing or consuming a file as it is downloaded, rather than while it is being downloaded. Streaming a file also allows the viewer to keep free space rather than keep the file on a local device. The restriction on the time at which a file is downloaded has to do with our own internet connection and availability and the file itself. It is important to realize what currently throttles user downloads is not "speed" but actually availability. Internet connectivity is best thought of as a highway and our experience improves more easily as the lanes increase, not as the speed limit increases.
Imagine our internet availability is a one lane highway aka 1 MbpS and we are trying to download a set of 10 cars aka a 10Mb file. I trust we can do that math, but it will take 10 seconds roughly to view this file in our browser. However, if your internet provider decided to allocate more lanes to you, say 5 lanes for 5 MbpS, that same file will take only 2 seconds to populate in your browser or download.
I think it is also worth noticing that file types themselves are not determinant of size or bandwidth need. In general text will be less size than richer media like video. According to Pottermore and iTunes the entire textual library of the Harry Potter story is .013 GB, the audio book library is 3.11 GB and the 8 movies are in total 37.63 in HD. This is supposedly the same content and story consumed. In fact, the books are much more robust in terms of content but are far less taxing in terms of file size.
As we move from a text on-demand society towards a rich-media on-demand society the current bandwidth allocations may not be enough for users. The drawbacks we experience include suboptimal waiting times and low, pixilated rich media. This matters because consuming a movie or television episode piecemeal is frustrating and may even compromise the user experience. This is most problematic with live consumption events like sports and breaking news. This type of fresh content needs to be consumed as it is produced for it to have its highest value. Think about how many reruns of a superbowl or breaking news event we watch compared to the live event.
The solutions for this issue revolve primarily around two different points of throttle, as you may guess, hardware and software. Improving the hardware experience means allocating more lanes to each internet user. According to netindex the average availability in the United States sits at 32.1 MbpS. By improving infrastructures and the amound of "lanes" available to allocate we could increase the average lane availability and therefore decrease wait times like we discussed in the 10 Mb example above. Increasing the aggregate lane availability amounts to physical infrastructure improvement, like laying more fiberoptic cables to transmit data.
We are also interested in the software side of the solution, file compression. There are two types of compression, lossless and lossy. Lossless compression uses statistical redundancy in code to reduce file sizes. This means not counting duplicated words twice for example but instead using callbacks and variables for size efficiency. Conversely, lossy compression types purposefully reduce meaningful parts of files that are hopefully not perceptible for users. In our analogy compression would mean reducing the actual amount of cars trying to traverse the highway while conveying exactly the same (lossless) or observably the same (lossy) media content.
From my understanding and research, it appears like the software development of video/streaming compression is good. Perhaps there is opportunity for software developers to see if human perception of rich media might tolerate lossy compression, but display types like HD might be a logical level users both enjoy and operates at the optimum perception level of "high quality" video streaming. Perhaps the solution for the increasing demand of rich media, particularly on mobile devices, will come more from hardware improvements and more "lane" availability to content consumers.


|
|||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
| Interface Summary | |
|---|---|
| ItemSchemePriceCalculator | ItemSchemePriceCalculator is the calculator that prices the item based on its pricing scheme. |
| Class Summary | |
|---|---|
| ComplexPriceDroplet | Given a complex price, returns the level information contained in it. |
| ConfigurableItemPriceListCalculator | This calculator assumes the ItemListPriceCalculator has already run. |
| ItemListPriceCalculator | A calculator which determines the list price of an item and sets the itemPriceInfo to be that amount. |
| ItemPriceCalculator | This class can either price a single commerce item or price a list of commerce items. |
| ItemSalePriceCalculator | Extends the super class to perform extended logic specific to handling an ItemPriceSource for sale prices. |
| ItemSalesPriceCalculator | A calculator that sets the sales price for a commerce item. |
| ItemSalesTieredPriceCalculator | A calculator which determines the sales tiered price of an item and sets the itemPriceInfo to be that amount. |
| ItemTieredPriceCalculator | A calculator which determines the tiered price of an item and sets the itemPriceInfo to be that amount. |
| PriceCacheAdapter | |
| PriceCacheKey | |
| PriceDroplet | Given a productId, a skuId, and a price list, returns the given price. |
| PriceListManager | Helper class to ease creation and manipulation of PriceLists. |
| PriceListProfilePropertySetter | Commerce specific implementation of the ProfilePropertySetter that sets set the price list properties of a profile from the current site. |
| Exception Summary | |
|---|---|
| PriceListException | Represents an exception thrown during price list processing. |
|
|||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |


07. Extra Support - Solidity Review
Solidity-Review 1
# Extra Support
In this section, we provide a brief Solidity review. For full developer documentation, review the following: https://solidity.readthedocs.io/en/v0.4.24/
Topics covered in this section are:
- Solidity versioning
- Contracts
- Variables
- Variable types
- Booleans
- Integers
- Addresses
- Strings
- Variable definition
- Arithmetics
- Arithmetic operations
- Structs
- Mappings
Solidity review
This page list common Solidity syntax. It's geared for a quick review as your working through the development of your smart contracts. For more depth, please review Solidity developer documentation: https://solidity.readthedocs.io/en/v0.4.24/
Solidity versioning
Solidity source files can contain any number of contract definitions. Each Solidity file also includes a thing called "Version Pragma". It is used to prevent the code from being compiled with future compiler versions that might introduce incompatible changes. Most of the time, the definition looks like this:
pragma solidity ^0.4.20;
In the example above 0.4.20 is the desired compiler version.
Contracts
Now, let's put it into code.
Contracts in Solidity are similar to classes in object-oriented languages. They contain data in variables and functions that can modify these variables.
They are defined by using a contract keyword, followed by the contract name and two brackets { } which will later enclose contract variables and functions. For example:
pragma solidity ^0.4.20;
contract ParentObject {
}
Variables
Wow! You've successfully created the frame of your contract! Now, it's time to start learning about how your contract will work. We'll start by finding out what type of variables there are.
Variable types
State variables are used to store information on the blockchain. They can also be manipulated by the functions within the contract.
Solidity is a statically typed programming language, meaning that each variable must have its type specified. Examples of the main data types:
Booleans
Can only have one of the two following values: true or false. The keyword for booleans is bool.
Integers
Integers can be split into main groups: regular integers (can store both positive and negative values) and unsigned integers (can only store values that are 0 or higher)
Regular integer has keywords from int8 to int256. The number signifies the maximum number of bits it can store (thus limiting the maximum value), and it can be any number between 8 and 256 as long as it incremented in steps of 8 (e.g., int16 is valid but int17is not). The int keyword alone would be understood as int256.
Unsigned integers follow the same logic. The only difference is the keyword which ranges from uint8 to uint256. Keyword uintcan also be used instead of uint256.
Addresses
The address keyword is used to hold Ethereum addresses. If you're planning to store an Ethereum address, you will need to use the address keyword.
Strings
The string variable is used to store text information. If you need to store a variable that should contain text information use the string keyword.
Variable definition
There are more data types, but we will go into more details in further lessons.
Variables and their values are defined like this.
contract Pizza {
bool isWarm = true;
uint slicesLeft = 3;
}
pragma solidity ^0.4.20;
contract ParentObject {
// Write your solution below
uint maxChildrenPerParentOpject = 10;
uint minChildrenPerParentOpject = 1;
}
Arithmetics
Now that you learned to define the variables for your contract, it's time to go through some basic math commands that will be useful later for defining your smart contract code.
Arithmetic operations
Integers can be used for arithmetic operations:
- Addition x + y
- Subtraction x - y
- Multiplication x * y
- Division x / y
- Remainder x % y
- Exponentiation x ** y (x to the power of y)
For example:
uint x = 16;
uint pizza = 4;
uint result = 0;
result = x + pizza; // 16 + 4 = 20
result = x - pizza; // 16 - 4 = 12
result = x * pizza; // 16 * 4 = 64
result = x / pizza; // 16 / 4 = 4
result = x % pizza; // 16 % 4 = 0
result = x ** pizza; // 16 ^ 4 = 65536
A real world example:
uint pizzaSlices = 6;
uint people = 2;
uint slicesPerPerson = pizzaSlices / people;
Structs
As we've learned the basics for defining variables, now we will learn to create the structure that defines your variables properties: name, type, coordinates (X and Y), and so forth.
Structs
A struct is a special data type that allows the programmer to group a list of variables.
Structures are defined like this:
struct Car {
string make;
string model;
uint16 year;
uint16 horsepower;
}
Mappings
Now that you've defined your variables, we'll learn how to create a variable that will later map your variable to the blockchain - a special list where all other variables are stored.
Mappings allow the programmer to create key-value pairs and store them as a list. Concepts like this also are known as hash tables.
Mappings are defined like this:
mapping(key_type => key_value) mappingName;
key_type should be replaced by a data type. Two commonly used variable types for mapping keys that we already know about are address and uint. It is important to note that not every data type can be used as a key. For instance, structs and other mappings cannot be used as keys.
Similarly, key_value should be replaced by the value type. Unlike with keys, Solidity does not limit the data type for values. It can be anything, including structs and other mappings.
A real-world example of a mapping:
mapping(address => uint256) balance;
This mapping could hold the bank account balance in uint256 for the given address.


Input Devices
This week lecture is to experiment with the input device in the embedded programming.
I decide to tell and try something about the PicMicro world, (because of the fact that i didn't have time to build my own Atmel based device at the Opendot, my fault)
The microchip produce a large variety of microcontroller 8, 16 and 32 bit based processor and register, also he produce a large variety of DSP with a high MIPS in data management and calculation.
By now I experiment the 8 bit line in different model of microcontroller( from the base line to the high end).
This micro can be programmed with a lot of IDE in free version and also with licensed IDE.
The Microchip's ones is called MPLABX and is a powerful tool with a lot of useful things like subroutine lookout, peripheral used, register control and so on.
also the microchip release for free a large volume of library written in c usable in all the IDE.
The processor of the compiler and linker is not really optimized in the free version but it didn't put limit to the usable program memory of the micro, so for non commercial things ( united to the large capacity of the PicMicro sounds good).
MPLABX homepage
Another IDE is developed by MikroElektronika and is downloadable for free in the base version who give a basic optimization and a limited size in programming memory.
It have a nice user interface and a nice console, and it will include a large variety of library( the program will only unlock the library usable on the pic you choose to use, evaluating the internal module).
It also have a nice user friendly section to set the fuses of the micro and set the register who set the function of the micro.
MikroElettronika homepage
All the two IDE have a direct section to upload the code in the micro via different tool (all the microchip programmer for the MPLABX and the MikroElektronika's programmer for that IDE), and all the two make a file HEX as output.
I decide to use the pickit2 (clone) to upload the HEX file in the PicMicro. It can be also replied because the microchip released the schematic and the firmware they put in the original one (made with a PicMicro).
microchip give free for the use a program to use the pickit2 as programmer and debugger.
The microchip programming technique is a bit different from the Atmel, it have a only line of data and a line of clock, the other 3 lines are ground, voltage (that can be modulated directly from the pickit2 program, so is possible to test the 5 volt micro and also the low voltage 3.3v and 1.8v), and the programming voltage.
The programming voltage is applied at the reset pin of the micro and if it go to 12-13v put the micro in the programming mode, so all the data that arrive on the two line clock and data will be flushed on the internal memory and register of the micro in serial mode.
HERE you can find some useful information about programming technique
A lot of things can be told about this devices but is not the mission of this week assignment, but I will soon build a programmer for the Pic family and make some researching in open software IDE.
for selecting the proper device you can see what you need and search in the long list of embedded peripheral in the PicMicro family.
I decide to implement a Capacitive Touch, so I search a PicMicro in the list with a CPS module so i choose the PIC16F1825.
The CPS module is Capacitive Sensing Module ( also called CSM) and reportet from the PIC datasheet is "The Capacitive Sensing (CPS) module allows for an interaction with an end user without a mechanical interface. In a typical application, the CPS module is
attached to a pad on a Printed Circuit Board (PCB),
which is electrically isolated from the end user. When the
end user places their finger over the PCB pad, a
capacitive load is added, causing a frequency shift in the
CPS module. The CPS module requires software and at
least one timer resource to determine the change in
frequency."
So is based on the fact that the human body have a little capacitance and by using it ( via touch, using the skin as a dielectric), is possible to make an influence in the frequency of an oscillator RC (resistor capacitor).
I read the data sheet and the application note from microchip and I start coding...
I follow the indication and make my own c program activating and the activating all the module i need.
HERE you can find the datasheet of the PIC16F1825
The module can connect a lot of input (pin of the micro) to an oscillator circuit and add the capacity that can be put on the pin by a human touch to the total capacity of the integrated circuit, in this way the generator will change the operational frequency he put in output.
So the way is use a time fix unit and count the oscillation the circuit do in this period, so we can detect if a touch happen.
This way need to use 2 different timer. Is also possible to switch easily to a different pin and remake the procedure.
The time needed to make a efficient detection is based on the speed of the oscillator and the precision of the module, so it can be a slow process (in therm of real time process).
Download the ZIP file of the c project and HEX
after the compile goes right i charge the hex in the pickit2 program and flash it....
in the picture you can see PIC12f1822 because i also try a similar code in that (it have the same pheripheral bit less pin)
Here is the program i write (i leave all the comment for a good understanding of what i made)
main
#include "touchpic.h"
//--------------------------------------
//core speed 16Mhz interni...
//tmr1 drived by fosc
//tmr0 drived by sense module cps
//intterrupr at owerflow of tmro e in case of error from tmr1
//ra5 led port
//-------------------------------------------------------
void InitializeSystem() { //Set up registers
//bit_clear(ANSELE, LED_E0|LED_E1); // LED ports set to digital *****
capacitive_sensor_settings();
//ledblink(2);
}
void main() {
char i; // CSO active channel
osccon=0b01111010;// 16mhz internal clock fuses
trisa=0;
trisc=0;
//lata=0;
ansela=0;
ansela.B4=1;
Sound_Init(&PORTa, 2);
InitializeSystem();
disable_interrupts(); // The delay_ms will cause timer IF
delay_ms(300);
//ledblink(2);
reset_system();
timer_presets();
initial_scan_channels(); // set 'off' CSO count for each channel
while(1) {
//ledblink(2);
i =0;
// repeatedly configure port until timer overflows, then handle it
// then increase the channelNumber.
reset_system();
// scan through each touch channel.
while (i <= 0){
configurePort();// repeated until timer overflows
if (interrupt_alarm) { // s/w interrupt alarm bit set by ISR
alarmInterrupt(); // handle interrupt flag
//uart1_write(channelNumber);
reset_system(); // Start again with a clean slate
i++ ;
} // end if
} // end while
disable_interrupts();
// in mTouch library, updates channel status register and writes changed
// channel status to UART.
update_channel_status();
//noChange is a flag for when channel status is changed.
/*if (noChange == false) { // changed i/p, so change LEDs
mcp_activechannels(); // work out which LEDs to light on board
mcp_update(LEDboard, MCPportA, MCPportB);// activate LEDs on board with status
noChange = true; // reset flag
}
if (noChange == true){ // do nothing if no change to status
//uart1_write(0x99); //TEST alive marker for debugging
} // end if ********/
} // end while(1)
}
touch routine i wrote
/* library for mTouch touch
For the PIC16F****,max of 16 channel capacitive touch
"just sends button status and not the CSO count for each channel"
*/
#ifndef _MTOUCH_5_H__
#define _MTOUCH_5_H__
#include "notes.h"
#define bit(num) (1 << num) // creates a bit mask
#define bit_set(v, m) ((v) |=(m)) // Sets the bit
// e.g. bit_set (PORTD, bit(0) | bit(1));
#define bit_clear(v, m) ((v) &= ~(m)) // Clears the bit
#define bit_toggle(v, m) ((v) ^= (m)) // toggle the bit
#define bit_read(v, m) ((v) & (m)) // read a bit and see if it is set
#define bit_test(v,m) ((v) && (m))
#define true 1
#define false 0
#define LED_E0 bit(0)
#define LED_E1 bit(1)
#define LED_E0_on() bit_clear(PORTE,LED_E0)
#define LED_E0_off() bit_set(PORTE,LED_E0)
#define LED_E1_on() bit_clear(PORTE,LED_E1)
#define LED_E1_off() bit_set(PORTE,LED_E1)
//#define t0Interrupt bit(0)
//#define t1Interrupt bit(1)
#define rcieInterrupt bit(2)
#define startChannel 3// h/w error on ch0 on '726 board
#define lastChannel 3 //***** ho modificato il numero di canali
#define numberChannels lastChannel-startChannel+1
#define PORTACapchannels 0b00110000
#define PORTBCapchannels 0b00111111
#define PORTDCapchannles
#define threshold 0x04 // threshold to trigger change on a CSO channel
#define timer1Off() (T1CON.TMR1ON = 0)
//------------------------------------------------------------------------------------------------------------
// TRIS values for all of the CPS pins to turn only the current ChannelNumber CPS and leave all others as ouputs
//------------------------------------------------------------------------------------------------------------
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
const char TRISACapOscOn[] = {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00010000,0b00100000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000};
const char TRISBCapOscOn[] = {0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000};
const char TRISDCapOscOn[] = {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000};
int activeChannels = 0x0000; // initialise to all off, 16 bits for 16 channels!
int initialTriggerCount; // Counter keeps track of how many samples we have taken since the last integration of the released average
int initialCapCount; // Counter keeps track of how many samples we have taken since the last integration of the released average
int capCount; // Store MSB of timer1 for each channel
int oldcapCount[numberChannels]; // Store old capCount
char noChange = true; // flag for changed sensor status
char interrupt_alarm = 0x00; // s/w alarm register, bit(0)=tmr0 IF, bit(1)=tmr1 IF, bit(2) = rcie IF
char t0_preload = 0x06; // preset = 0
char t0Interrupt =0;
char t1Interrupt =0;
char ison=0;
//char touch=0;
//-------------------------------------------------------------------------------------
//*******************************aggiunto da NOTES.H**********************************
//-------------------------------------------------------------------------------------
int pauseBetweenNotes;
int noteduration;
int typesound=0;
//int threshold = 150;
//unsigned int pressCount = 0;
int thisnote;
int coin_sound_num_notes = 2;
int coin_sound_notes[] = {NOTE_D6 , NOTE_G6};
int coin_sound_note_durations[] = {16, 2};
int oneup_sound_num_notes = 6;
int oneup_sound_notes[] = {NOTE_E6, NOTE_G6, NOTE_E7, NOTE_C7, NOTE_D7, NOTE_G7};
int oneup_sound_note_durations[] = {8, 8, 8, 8, 8, 8};
/*
CapSense cs_4_2 = CapSense(CAP_SENSOR_SEND_PIN, CAP_SENSOR_RECEIVE_PIN);
*/
/*
void setup() {
pinMode(10, INPUT);
pinMode(LIGHT_PIN, OUTPUT);
digitalWrite(LIGHT_PIN, HIGH);
delay(1000);
digitalWrite(LIGHT_PIN, LOW);
// tone(SPEAKER_PIN, NOTE_G7);
}
*/
void playSound(int num_notes, int notes[], int durations[]) {
// iterate over the notes of the melody:
for ( thisNote = 0; thisNote < num_notes; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
noteDuration = 1000/durations[thisNote];
Sound_Play(notes[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
pauseBetweenNotes = noteDuration * 0.30;
Vdelay_ms(pauseBetweenNotes);
// stop the tone playing:
//noTone(speaker_pin);
}
}
//-------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
/*
// Port expander module connections
sbit SPExpanderRST at RC0_bit;
sbit SPExpanderCS at RC1_bit;
sbit SPExpanderRST_Direction at TRISC0_bit;
sbit SPExpanderCS_Direction at TRISC1_bit;
// End port expander module connections
*/
/* void fast_flash_E0(void) { // flash LED E0
bit_clear(TRISE, LED_E0);
LED_E0_off();
Delay_ms(200);
LED_E0_on();
Delay_ms(300);
LED_E0_off();
}
void fast_flash_E1(void) { // flash LED E1
bit_clear(TRISE, LED_E1);
LED_E1_off();
Delay_ms(200);
LED_E1_on();
Delay_ms(300);
LED_E1_off();
}
*/
void ledblink(int num){
int a;
for (a=0;a defines active pin
//UART_out("tmr1 IF\n");
//delay_ms(300);
//UART_out(t1InterruptTxt);
//uart_out("\n"); // new line
//delay_ms(500);
flag_clear;
//bit_clear(interrupt_alarm,t1Interrupt); // clear alarm flag for tmr1 interrupt
}// end if
/*
if bit_read(interrupt_alarm, rcieInterrupt) { // uart rx flag]
char rcieInterruptTxt[7];
// disable_interrupts();
IntToStr(RCREG, rcieInterruptTxt); //uart rx text
//UART_out("rcie IF\n");
//uart_out(rcieInterruptTxt); // write back received text
//uart_out("\n"); // new line
if (RCREG == 4) {
uartTrigger();
} // end if
bit_clear(interrupt_alarm,rcieInterrupt); // clear alarm flag
} // end if
*/
} // end alarmInterrupt
/*
void uart_write_short(short var) {
uart1_write(var);
}
*/
// Configure tris & CPSCON1 settings for channel
void configurePort() {
CPSCON1.CPSCH0= 1; // Set CSO to active channel
CPSCON1.CPSCH1= 1; // Set CSO to active channel
//ansela.B4=1;
trisa.B4=1;
//uart_write_short(CPSCON1); // debug info
/* if (channel < 6) {
TRISB = TRISBCapOscOn[channel]; // Channels 0-5 on portB
}
else if (channel < 8){
TRISA = TRISACapOscOn[channel]; // Channels 6-7 on portA
}
else {
TRISD = TRISDCapOscOn[channel]; // Channels 8-15 on portD
}
*/
}
/*
void scan_channels(){ // get CSO count for each channel
char channel=0;
while (channel <= 0){
configurePort();// repeated until timer overflows
if (interrupt_alarm) { // s/w interrupt alarm bit set by ISR
alarmInterrupt(); // handle interrupt flag
reset_system(); // Start again with a clean slate
channel++ ;
} // end if
} // end while
}// end scan_channels
*/
void initial_scan_channels(){ // set initial CSO count threshold for each channel
//char channel = 0;
char find=0;
//while (channel <= 0){
while (find<=0) {
if (interrupt_alarm) { // s/w interrupt alarm bit set by ISR
alarmInterrupt(); // handle interrupt flag
initialTriggerCount = capCount+threshold;
initialCapCount = capCount+(threshold-1);
reset_system(); // Start again with a clean slate
//channel++ ;
find++;
} // end if
} // end while
}// end scan_channels
/********************
// error - tmr1 overflowed before tmr0
void tmr1_overflow_debug(short var){
char errorTxt[7];
disable_interrupts();
uart_out("Timer1 IF");
delay_ms(500);
IntToStr(var, errorTxt);
uart_out(errorTxt);
delay_ms(500);
} // end tmr1_overflow_debug
*/
/*void debug(int var) { // writes debug info to LCD
char debugText[7];
disable_interrupts();
IntToStr(var, debugText);
// SPI_LCD_write(1,1,"debug text");
uart_out("debug text");
delay_ms(500);
// SPI_LCD_write(2,1,debugText);
uart_out(debugText);
delay_ms(500);
} // end debug
*/
/*
// send info of a channel turning ON to uart
void uart_channel_on(char channel) {
// set bit 6 high to avoid any 0x00 being sent as data
bit_set(channel, bit(6));
// set bit 5 high to indicate channel turned ON
bit_set(channel, bit(5));
uart1_write(channel);
//uart1_write(0xAA); // for testing
} // end uart_channel_on
void uart_channel_off(char channel) {
// set bit 6 high to avoid any 0x00 being sent as data
bit_set(channel, bit(6));
// set bit 5 low to indicate channel turned OFF, should be anyway
bit_clear(channel, bit(5));
uart1_write(channel);
//uart1_write(0xEE); // testing
} // end uart_channel_off
*/
// update activeChannels register with on/off info
// send changed channels to uart
int update_channel_status(int touch) { // update activeChannels with on/off info
//unsigned int tempactiveChannels; // used for debugging
char channel = 0; // channel counter
//portc=capcount;
while(channel <= 0) // scroll through each channel
{
// channel CSO count increased - channel turned ON
if (capCount > initialTriggerCount){/* &&
!bit_read(activeChannels, bit(channel))******/
//portc=capcount;
//noChange = false; // there's been a change
//bit_set(activeChannels, bit(channel)); // flag this channel as on
//disable_interrupts();
//ledblink(2);
//porta.b5=1;
if (!(touch==1)){
touch=1;
if(ison==0){
ison=1;
porta.b5=1;
}//endif
}//endif
else {
ison=0;
porta.b5=0;
}//endelse
} // end if
}
// channel CSO count decreased - channel turned OFF
if ((capCount < initialcapCount)&(touch==1)&(!(capcount>initialTriggerCount))){/* && bit_read(activeChannels, bit(channel))*****/
//noChange = false; // there's been a change
//bit_clear(activeChannels, bit(channel)); // flag this channel as off
//portc=capcount;
//disable_interrupts();
touch=0;
//porta.b5=0;
//ledblink(1);
// uart changed channel
//uart_channel_off(channel); // send channel off status to uart ***
} // end if
//UART1_Write(capCount);
capCount=0;
channel++;
//delay_ms(250);
} // end while
/* for debugging, writes out the activated channels
if (noChange == false) { // for debugging, write both bytes of activeChannels to UART
tempactiveChannels = activeChannels;
uart1_write(tempactiveChannels);// write 8 LSB
tempactiveChannels = tempactiveChannels >> 8; // shift MSB to LSB location
uart1_write(tempactiveChannels); // write 8 MSB
} // end if
*/
return(touch);
} // end update_channel_status
#endif
test and work...
What i read with this sensor?
The sensor that i made is a proximity sensor who detect the near of a human (or animal) body (or a piece of the body like hands finger) and take an action at a give threshold.
The threshold is given via software ( and in my script is setted at the start so if you turn on the circuit you can decide the distance of activation by holding the hand at the distance you want the activation occur).
In this case the effect taken at the activation is to toggle the led.
other thing will be made...


Reset your folder
Use the tools on this page to resync your folder or rebuild your site. If everything works as it should, you shouldn't need to use them. Please don't hestiate to contact support.
{{message}} {{fromNow}}


LINKEN'S SPHERE
5175
Passive: Spellblock - Blocks most targeted spells once every 17 seconds.
+
15
All Attributes
+
6
HP Regeneration
+
150%
Mana Regeneration
+
10
Damage
This magical sphere once protected one of the most famous heroes in history.
Recipe:


Key features of our workshop
About
This workshop is designed for people who want to engage their abilities in terms of digital arts and also for people who want to foster imagination and creativity.
Theme
The theme of our workshop is yet to be revealed as it is up to our attendees which helps them to be more interested and comfortable.
Goals
Our expectation is that as students leave, they will be enthusiastic, positive in their skills, and eager to learn more.
Participants
We welcome people from 12 to 15 because it would be easier for us to educate them and understand them better. This also creates an environment where they can be themselves without any problems and just overall fun without taking out learning.
We believe that art history is an essential element of understanding art as well as the perception of art. Through encouragement and support, we develop confidence in our participants. Our expectation is that as students leave, they will be enthusiastic, positive in their skills, and eager to learn more. The theme of our workshop is yet to be revealed as it is up to our attendees which helps them to be more interested and comfortable.
Behind the workshop
Facilitator
Spokeperson
Researcher
Scribe
Different art types
Join our workshop and Let's have fun!!
Apec Schools
Email: ap.kristinerose.montiel@apecschools.edu.ph


This sheltered harbour lies on the southern coast of the island of St Thomas. Charlotte Amalie is the capital of the US Virgin Islands and is a popular port of call for cruise ships.
Position 18 20'17"N, 64 56'17"W. (opposite Reporting Office)
Position 18 19'57"N, 64 57'04"W (Crown Bay marina)
If arriving outside local working hours, report your arrival leaving a brief message with boat name, registration number, date and time of arrival and a return telephone number.
The captain should go ashore and obtain preliminary clearance at the offices on the western end of the waterfront next to the seaplane landing. All crew must then go with their completed papers to customs and immigration at the ferry dock. One crew member is allowed to stay on board as an anchor watch. However, if not a US national he or she will have to clear in person later at the same place.
Last updated March 2016.
There are two IGY Marinas in St. Thomas, American Yacht Harbour and Yacht Haven Grande.
Cruising yachts tend to gather at Crown Bay, with anchorage across from the mouth of the marina. Close to Tickles Pub.
At the eastern end of the island, there are several small marinas in Benner Bay, Vessup Bay and around Red Hook.
Photo of Crown Bay marina © www.crownbay.com
Last updated March 2016.


Conduct a study of modern Natural Language Processing (NLP) tools for analysis of clinical notes from the de-identifed and publicily available MIMIC database. Perform literature reviews, reproduce results from recent studies, and write reports comparing his findings to previously reported results.
Utilize Estimote Beacons and stickers to find practical applications in healthcare. For instance, one may use them to measure patient-clinician interactions or patient-family member interactions. Potentially, it would be experienced in every ICU patient's room, and serve as an indoor GPS.
Developing Augmented Reality protein models that will be used in biochemistry courses. Utilize HoloLens-Based Augmented Reality to improve current flat screen monitor's limitations, and to convey the full three dimensional characteristics of sophisticated-structured molecules.
Annual Summer Scholar Project sponsored by ViaSat. I worked alongside a university professor and collaborated with another senior student. While working on this project we produced online visual tutoring systems for learning required programming and mathematics in computer sciences courses.
Worked alongside other STEM ambassadors to guide, teach, and help after school programs among 10 middle schools in Vista, San Marcos, and Escondido.


Aliright, may be not best but we tried
Expensive but bad sound
Cheeaper models are better but do not tell anyone
No one died of it
You pay and see what happens
Pets approved
Cats like it
Just watch!
Cheap
$300
Lorem ipsum.
Lorem ipsum.
Lorem ipsum dolor.
Lorem ipsum.
Select
Just for you
$900
Lorem ipsum.
Lorem ipsum.
Lorem ipsum dolor
Lorem ipsum.
Select
Overpriced like apple
$1200
Try another shop
We speak frankly
Lorem ipsum dolor
Lorem ipsum
Select
read more about drums