The Unfun Cat
The Unfun Cat

Reputation: 32008

Add vector to each row of a dataframe

I have a vector to_add which looks like this:

> to_add
  X0 X3 X6 X9 X12 X18 X21
1  6  0  4  1   5   3   6

I'd like to add it to every row of my dataframe data, which looks like this:

> head(data)
                         X0 X3 X6 X9 X12 X18 X21
chr5_89951600_89954799   18 26 19 22  29  30  23
chr16_70874600_70876999  15 26 25 14  18  23  16
chr2_51953000_51955199    7 26  7 14  26  17  33
chr3_143120600_143123799 25 40 35 23  25  28  31
chr15_34771400_34774599  27 42 31 21  24  15  34
chr2_13077000_13083999   36 73 52 48  73  54  53

How do I do this efficiently? I doubt writing a loop is the cleverest way...

Unfortunately, data + to_add does not work, even though data + 1 does...

And data + as.numeric(to_add)

did not do what I wanted- the results are wrong!

> head(data + as.numeric(to_add))
                         X0 X3 X6 X9 X12 X18 X21
chr5_89951600_89954799   24 32 25 28  35  36  29
chr16_70874600_70876999  15 26 25 14  18  23  16
chr2_51953000_51955199   11 30 11 18  30  21  37
chr3_143120600_143123799 26 41 36 24  26  29  32
chr15_34771400_34774599  32 47 36 26  29  20  39
chr2_13077000_13083999   39 76 55 51  76  57  56

Ps. I'm doing this to make all the column medians the same, so a simpler way of making the column medians the same than just adding the difference between the column median and the column with the max median value would be appreciated.

Upvotes: 0

Views: 2134

Answers (3)

IRTFM
IRTFM

Reputation: 263481

There's a specific function for this purpose:

sweep(data, 2, to_add, "+")
                         X0 X3 X6 X9 X12 X18 X21
chr5_89951600_89954799   24 26 23 23  34  33  29
chr16_70874600_70876999  21 26 29 15  23  26  22
chr2_51953000_51955199   13 26 11 15  31  20  39
chr3_143120600_143123799 31 40 39 24  30  31  37
chr15_34771400_34774599  33 42 35 22  29  18  40
chr2_13077000_13083999   42 73 56 49  78  57  59

It applies a particular function across all items of a "margin" using the values in the "statistic". It's the mean of that margin (and here you want columns) by default, but it can be any vector of the same length as the margin.

Upvotes: 2

akrun
akrun

Reputation: 887881

You could do

data + to_add[col(data)]
#                         X0 X3 X6 X9 X12 X18 X21
#chr5_89951600_89954799   24 26 23 23  34  33  29
#chr16_70874600_70876999  21 26 29 15  23  26  22
#chr2_51953000_51955199   13 26 11 15  31  20  39
#chr3_143120600_143123799 31 40 39 24  30  31  37
#chr15_34771400_34774599  33 42 35 22  29  18  40
#chr2_13077000_13083999   42 73 56 49  78  57  59

Upvotes: 4

The Unfun Cat
The Unfun Cat

Reputation: 32008

Thanks, thelatemail!

result <- data.frame(Map("+",data,to_add),row.names=rownames(data))

> head(result)
                         X0 X3 X6 X9 X12 X18 X21
chr5_89951600_89954799   24 26 23 23  34  33  29
chr16_70874600_70876999  21 26 29 15  23  26  22
chr2_51953000_51955199   13 26 11 15  31  20  39
chr3_143120600_143123799 31 40 39 24  30  31  37
chr15_34771400_34774599  33 42 35 22  29  18  40
chr2_13077000_13083999   42 73 56 49  78  57  59

If you decide to add this as an answer later I will delete mine and accept yours, thelatemail.

Upvotes: 1

Related Questions