Update an Entire Row in Data.Table in R

Update an entire row in data.table in R

You could use names(d) for LHS, then use as.list in order to convert your vector to a list so data.table will understand that it need to assign each value to a different column instead all the values to each column.

You are also converting character vector to numeric here (the x column), so data.table will return a warning in order to make sure you are aware of that.

vec <- c(5, 5, 5, 5)
d[q == 1L, names(d) := as.list(vec)][]
# q x y v
# 1: 5 5 5 5
# 2: 2 a 3 2
# 3: 3 a 6 3
# 4: 4 b 1 4
# 5: 5 b 3 5
# 6: 6 b 6 6
# 7: 7 c 1 7
# 8: 8 c 3 8
# 9: 9 c 6 9

Using data.table syntax to update column

We can do this by converting the logical vector to binary with as.integer

DT[, QTY := as.integer(QTY>0)]
DT
# ID QTY
#1: 1 0
#2: 2 1
#3: 2 1
#4: 4 0
#5: 5 1
#6: 6 1

Or specify it in the i and update the 'QTY'

DT[QTY>0, QTY := 1]

R data.table simple replacing of a whole row

xx[1, (colnames(xx)):= list(1,2)]

sequentially update rows in data.table

I'd write a simple Rcpp function instead of spending time trying to find a vectorized R solution:

library(Rcpp)
sourceCpp(code = "
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::IntegerVector myfun(const Rcpp::IntegerVector x, const Rcpp::IntegerVector y) {
Rcpp::IntegerVector res = x;
res(0) = x(0) + y(0);
for (int i=1; i<x.length(); i++) {
if (x(i) >= res(i-1)) res(i) += y(i);
else res(i) = res(i-1) + y(i);
}
return res;
}
")
tempData[, enddt1 := myfun(startdt, daysupp)]
# drugName startdt daysupp enddt enddt1
#1: Aspirine 2012-01-01 30 2012-01-31 2012-01-31
#2: Aspirine 2012-01-20 30 2012-03-01 2012-03-01
#3: Aspirine 2012-02-15 10 2012-03-11 2012-03-11
#4: Aspirine 2012-03-10 20 2012-03-31 2012-03-31

Update rows of data frame in R

We can use match to get the row index. Using that index to subset the rows, we replace the 2nd and 3rd columns of the first dataset with the corresponding columns of second dataset.

ind <- match(df2$ID, df1$ID)
df1[ind, 2:3] <- df2[2:3]
df1
# ID Measurement1 Measurement2
#1 1 45 104
#2 2 10 11
#3 3 23 99
#4 4 21 22

Or we can use data.table to join the dataset on the 'ID' column (after converting the first dataset to 'data.table' i.e. setDT(df1)), and assign the 'Cols' with the 'iCols' from the second dataset.

 library(data.table)#v1.9.6+
Cols <- names(df1)[-1]
iCols <- paste0('i.', Cols)
setDT(df1)[df2, (Cols) := mget(iCols), on= 'ID'][]
# ID Measurement1 Measurement2
#1: 1 45 104
#2: 2 10 11
#3: 3 23 99
#4: 4 21 22

data

df1 <- structure(list(ID = 1:4, Measurement1 = c(45L, 34L, 23L, 56L), 
Measurement2 = c(104L, 87L, 99L, 67L)), .Names = c("ID",
"Measurement1", "Measurement2"), class = "data.frame",
row.names = c(NA, -4L))

df2 <- structure(list(ID = c(2L, 4L), Measurement1 = c(10L, 21L),
Measurement2 = c(11L,
22L)), .Names = c("ID", "Measurement1", "Measurement2"),
class = "data.frame", row.names = c(NA, -2L))

Learning data.table - how to update values by row number and column name

Or you can do this:

x <- names(my_dt)[1:5]

my_dt[, (x) := lapply(.SD, as.numeric), .SDcols = x]

my_dt[2, (x):= as.list(replacement)]

First we convert the target columns in my_dt to numeric. .SDcols represents the subset of columns in .SD that we are interested in. .SD holds all the columns in the data.table (except the ones used in by).

Once we convert the target columns to numeric, we update the values by reference.

Note: It is not necessary to define x beforehand, everything can be done on the fly. However, if you define x, you need to wrap it in () to make sure data.table doesn't look for the column x

R Data.Table: Dynamically Update a Different Column for each Row

With the OP's code, replace can work

test[, (2:4) := replace(.SD, which.max(.SD), max(.SD, na.rm = TRUE) - 0.1 * ttl), 
by = 1:nrow(test),.SDcols = 2:4]

-output

> test
thing1 A B C ttl
1: AAA 8.9 2.0 6.0 1
2: BBB 5.0 6.9 2.0 1
3: CCC 4.0 2.0 4.7 3
4: DDD 2.0 5.8 4.0 2
5: EEE 4.9 3.0 1.0 1

In base R, this may be faster with row/column indexing

test1 <- as.data.frame(test)
m1 <- cbind(seq_len(nrow(test1)), max.col(test1[2:4], "first"))
test1[2:4][m1] <- test1[2:4][m1] - 0.1 * test1$ttl


Related Topics



Leave a reply



Submit