Aggregating columns of a data frame
I have a data.frame like this:
>data
ID Orginal Modified
Sam_1 M K
Sam_1 K M
Sam_1 I J
Sam_1 M K
Sam_1 K M
Sam_2 K M
Sam_2 M K
Sam_3 J P
Sam_4 K M
Sam_4 M K
Sam_4 P J
I would like to calculate that for each sample number, times in the M column "Original" is converted to K in the "Modified" column and "K" in the "Original" column to "M" in the columns Modified and reported in the tab delim text as follows:
>newdata
ID M_to_K_counts K_to_M_counts
Sam_1 2 2
Sam_2 1 1
Sam_3 0 0
Sam_4 1 1
I tried the following code but it failed:
counts=function()
{
for(i in 1:dim(rnaseqmut)[1])
{
mk_counts=0
km_counts=0
if(data$Original[i]=='M' & data$Modified[i]== 'K')
{
mk_counts=mk_counts+1
}
if(data$Original[i]=='K' & data$Modified[i]== 'M')
{
km_counts=km_counts+1
}
}
print(mk_counts)
print(km_counts)
}
How can I achieve the format I want.
source to share
One option would be to use data.table
. Convert 'data.frame' to 'data.table' ( setDT(data)
). Grouped by the "ID" column, we get sum
items that are "M" for "Orginal" and "K" for "Modified" ("MtoKcount"), similarly, "KtoMcount" is obtained by doing the opposite.
library(data.table)
setDT(data)[, list(MtoKcount=sum(Orginal=='M' & Modified=='K'),
KtoMcount = sum(Orginal=='K' & Modified=='M')), by = ID]
# ID MtoKcount KtoMcount
#1: Sam_1 2 2
#2: Sam_2 1 1
#3: Sam_3 0 0
#4: Sam_4 1 1
Another option table
from base R
. We are paste
columns other than the "ID" ( do.call(paste0, data[-1])
) column and get the frequency counter with table
. Then we multiply the table output ('tbl') which only has "KM" or "MK" as column names
tbl <- table(data$ID,do.call(paste0, data[-1]))[,c('KM', 'MK')]
tbl
# KM MK
#Sam_1 2 2
#Sam_2 1 1
#Sam_3 0 0
#Sam_4 1 1
As @ user295691 mentioned in the comments, we can change the column names and paste
ing.
tbl <- with(data, table(ID, paste0(Orginal, "_to_", Modified,"_counts")))
tbl[,c('K_to_M_counts', 'M_to_K_counts')]
data
data <- structure(list(ID = c("Sam_1", "Sam_1", "Sam_1", "Sam_1",
"Sam_1",
"Sam_2", "Sam_2", "Sam_3", "Sam_4", "Sam_4", "Sam_4"), Orginal = c("M",
"K", "I", "M", "K", "K", "M", "J", "K", "M", "P"), Modified = c("K",
"M", "J", "K", "M", "M", "K", "P", "M", "K", "J")), .Names = c("ID",
"Orginal", "Modified"), class = "data.frame", row.names = c(NA,
-11L))
source to share
Using dplyr
x <- data.frame(ID = c(rep("Sam_1", 5), rep("Sam_2", 2), "Sam_3", rep("Sam_4", 3)),
Orginal = c("M", "K", "I", "M", "K", "K", "M", "J", "K", "M", "P"),
Modified = c("K", "M", "J", "K", "M", "M", "K", "P", "M", "K", "J"))
x %>%
group_by(ID) %>%
summarise(M_to_K_counts = length((Orginal == "M")[Modified == "K"]),
K_to_M_counts = length((Orginal == "K")[Modified == "M"]))
# Source: local data frame [4 x 3]
# ID M_to_K_counts K_to_M_counts
# 1 Sam_1 2 2
# 2 Sam_2 1 1
# 3 Sam_3 0 0
# 4 Sam_4 1 1
source to share