Asked  7 Months ago    Answers:  5   Viewed   34 times

I have a data.table with which I'd like to perform the same operation on certain columns. The names of these columns are given in a character vector. In this particular example, I'd like to multiply all of these columns by -1.

Some toy data and a vector specifying relevant columns:

library(data.table)
dt <- data.table(a = 1:3, b = 1:3, d = 1:3)
cols <- c("a", "b")

Right now I'm doing it this way, looping over the character vector:

for (col in 1:length(cols)) {
   dt[ , eval(parse(text = paste0(cols[col], ":=-1*", cols[col])))]
}

Is there a way to do this directly without the for loop?

 Answers

69

This seems to work:

dt[ , (cols) := lapply(.SD, "*", -1), .SDcols = cols]

The result is

    a  b d
1: -1 -1 1
2: -2 -2 2
3: -3 -3 3

There are a few tricks here:

  • Because there are parentheses in (cols) :=, the result is assigned to the columns specified in cols, instead of to some new variable named "cols".
  • .SDcols tells the call that we're only looking at those columns, and allows us to use .SD, the Subset of the Data associated with those columns.
  • lapply(.SD, ...) operates on .SD, which is a list of columns (like all data.frames and data.tables). lapply returns a list, so in the end j looks like cols := list(...).

EDIT: Here's another way that is probably faster, as @Arun mentioned:

for (j in cols) set(dt, j = j, value = -dt[[j]])
Tuesday, June 1, 2021
 
BradM
answered 7 Months ago
25

Many built-in operations like sum and prod are already able to operate across rows or columns, so you may be able to refactor the function you are applying to take advantage of this.

If that's not a viable option, one way to do it is to collect the rows or columns into cells using mat2cell or num2cell, then use cellfun to operate on the resulting cell array.

As an example, let's say you want to sum the columns of a matrix M. You can do this simply using sum:

M = magic(10);           %# A 10-by-10 matrix
columnSums = sum(M, 1);  %# A 1-by-10 vector of sums for each column

And here is how you would do this using the more complicated num2cell/cellfun option:

M = magic(10);                  %# A 10-by-10 matrix
C = num2cell(M, 1);             %# Collect the columns into cells
columnSums = cellfun(@sum, C);  %# A 1-by-10 vector of sums for each cell
Thursday, June 3, 2021
 
Isky
answered 7 Months ago
77

You simply use the apply() function:

R> M <- matrix(1:6, nrow=3, byrow=TRUE)
R> M
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
R> apply(M, 1, function(x) 2*x[1]+x[2])
[1]  4 10 16
R> 

This takes a matrix and applies a (silly) function to each row. You pass extra arguments to the function as fourth, fifth, ... arguments to apply().

Wednesday, June 9, 2021
 
Fishingfon
answered 6 Months ago
73

sSwfPath : Flash file Security is the Issue:

Solution:

Step 1: Check For sDom Property.

Step 2: Check the SWF Path is correct. If its correct

Step 3: Open Flash Manager :

http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html

Under 3rd Tab, Global Settings Add the Site Url Which contains SWF Path. Select Always Allow Option.

Then Try the Save PDF By Refresh.

Saturday, July 31, 2021
 
Pascal
answered 5 Months ago
75

Based on the OP's clarification, it could be

out <- reshape(dat[setdiff(names(dat), 'item_type')], idvar = c('person_id', 'gender'), direction = 'wide', timevar = 'item_id')
dim(out)
#[1]  2000 16006

out[1:3, c(1:3, 16000:16006)]
#   person_id gender item_trans.1 item_trans.15998 item_trans.15999 item_trans.16000 item_trans.16001 item_trans.16002 item_trans.16003
#1          1   MALE     5.091636               NA               NA               NA               NA               NA               NA
#32         2   MALE           NA               NA               NA               NA               NA               NA               NA
#64         3 FEMALE           NA               NA               NA               NA               NA               NA               NA
#   item_trans.16004
#1                NA
#32               NA
#64               NA
Saturday, December 4, 2021
 
Tushar Garg
answered 2 Days ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share