Reputation: 1499
I have a date.frame that looks like:
SNP CLST A1 A2 FRQ IMP POS CHR BVAL
1 rs2803291 Brahui C T 0.660000 0 1882185 1 878
2 rs2803291 Balochi C T 0.750000 0 1882185 1 878
3 rs2803291 Hazara C T 0.772727 0 1882185 1 878
4 rs2803291 Makrani C T 0.620000 0 1882185 1 878
5 rs2803291 Sindhi C T 0.770833 0 1882185 1 878
6 rs2803291 Pathan C T 0.681818 0 1882185 1 878
53 rs12060022 Brahui T C 0.0600000 1 3108186 1 982
54 rs12060022 Balochi T C 0.0416667 1 3108186 1 982
55 rs12060022 Hazara T C 0.0000000 1 3108186 1 982
56 rs12060022 Makrani T C 0.0200000 1 3108186 1 982
57 rs12060022 Sindhi T C 0.0625000 1 3108186 1 982
58 rs12060022 Pathan T C 1 1 3108186 1 982
105 rs870171 Brahui T G 0.2200000 0 3332664 1 976
106 rs870171 Balochi T G 0.3333330 0 3332664 1 976
107 rs870171 Hazara T G 1 0 3332664 1 976
108 rs870171 Makrani T G 1 0 3332664 1 976
109 rs870171 Sindhi T G 0.2083330 0 3332664 1 976
110 rs870171 Pathan T G 1 0 3332664 1 976
157 rs4282783 Brahui G T 1 1 4090545 1 992
158 rs4282783 Balochi G T 1 1 4090545 1 992
159 rs4282783 Hazara G T 1 1 4090545 1 992
160 rs4282783 Makrani G T 1 1 4090545 1 992
161 rs4282783 Sindhi G T 1 1 4090545 1 992
162 rs4282783 Pathan G T 1 1 4090545 1 992
I would like to delete all rows where every single line for the given SNP has a value of 1 in the FRQ
column. For example, every rs4282783 has a value of 1 in the FRQ column so I would like to delete all of those rows. But I don't want to delete row 58 for example which has a 1 value in FRQ. Does anyone have any advice?
Upvotes: 0
Views: 184
Reputation: 886948
Here is a data.table
based approach. Convert the 'data.frame' to 'data.table' (setDT(df)
), grouped by 'SNP', if
not (!
) all
the elements in 'FRQ' is 1, then get the Subset of Data.table.
library(data.table)
setDT(df)[, if(!(all(FRQ==1))) .SD , by = SNP]
Or a general approach if I may guess that the OP meant to delete all SNPs having only a single "FRQ", then we can use uniqueN
to find the number of unique
elements and use in the if
condition to keep only those having more than 1
setDT(df)[, if(uniqueN(FRQ) > 1) .SD , by = SNP]
Upvotes: 2
Reputation: 38500
Here is a base R method using subsetting and ave
. ave
constructs the group-level (SNP-level) maximum, which is used to subset the data by observation:
df[ave(df$FRQ, df$SNP, FUN=max) < 0.99999,]
SNP CLST A1 A2 FRQ IMP POS CHR BVAL
1 rs2803291 Brahui C T 0.660000 0 1882185 1 878
2 rs2803291 Balochi C T 0.750000 0 1882185 1 878
3 rs2803291 Hazara C T 0.772727 0 1882185 1 878
4 rs2803291 Makrani C T 0.620000 0 1882185 1 878
5 rs2803291 Sindhi C T 0.770833 0 1882185 1 878
6 rs2803291 Pathan C T 0.681818 0 1882185 1 878
Note that I used 0.99999 rather than 1 in order to avoid or reduce numerical imprecision issues.
data
df <- read.table(header=T, text="SNP CLST A1 A2 FRQ IMP POS CHR BVAL
1 rs2803291 Brahui C T 0.660000 0 1882185 1 878
2 rs2803291 Balochi C T 0.750000 0 1882185 1 878
3 rs2803291 Hazara C T 0.772727 0 1882185 1 878
4 rs2803291 Makrani C T 0.620000 0 1882185 1 878
5 rs2803291 Sindhi C T 0.770833 0 1882185 1 878
6 rs2803291 Pathan C T 0.681818 0 1882185 1 878
53 rs12060022 Brahui T C 0.0600000 1 3108186 1 982
54 rs12060022 Balochi T C 0.0416667 1 3108186 1 982
55 rs12060022 Hazara T C 0.0000000 1 3108186 1 982
56 rs12060022 Makrani T C 0.0200000 1 3108186 1 982
57 rs12060022 Sindhi T C 0.0625000 1 3108186 1 982
58 rs12060022 Pathan T C 1 1 3108186 1 982
105 rs870171 Brahui T G 0.2200000 0 3332664 1 976
106 rs870171 Balochi T G 0.3333330 0 3332664 1 976
107 rs870171 Hazara T G 1 0 3332664 1 976
108 rs870171 Makrani T G 1 0 3332664 1 976
109 rs870171 Sindhi T G 0.2083330 0 3332664 1 976
110 rs870171 Pathan T G 1 0 3332664 1 976
157 rs4282783 Brahui G T 1 1 4090545 1 992
158 rs4282783 Balochi G T 1 1 4090545 1 992
159 rs4282783 Hazara G T 1 1 4090545 1 992
160 rs4282783 Makrani G T 1 1 4090545 1 992
161 rs4282783 Sindhi G T 1 1 4090545 1 992
162 rs4282783 Pathan G T 1 1 4090545 1 992")
Upvotes: 2
Reputation: 1364
@imo's answer is neater but as I've done mine I'll add it. To my mind the logic is slightly clearer.
# which SNPs are always 1
# For each SNP value, take the rows with that SNP, and test if all FRQ values are 1
rmSNPs <- sapply(unique(dd$SNP), function(x) all(dd$FRQ[dd$SNP == x] == 1))
# new data is old data minus row where dd$SNP is not one of those found above
newdata <- dd[dd$SNP != unique(dd$SNP)[rmSNPs], ]
Upvotes: 2
Reputation: 21621
To remove SNP
where all values of FRQ
is equal to 1, you could try:
library(dplyr)
df %>%
group_by(SNP) %>%
filter(!all(FRQ == 1))
Which gives:
# SNP CLST A1 A2 FRQ IMP POS CHR BVAL
# <fctr> <fctr> <fctr> <fctr> <dbl> <int> <int> <int> <int>
#1 rs2803291 Brahui C T 0.6600000 0 1882185 1 878
#2 rs2803291 Balochi C T 0.7500000 0 1882185 1 878
#3 rs2803291 Hazara C T 0.7727270 0 1882185 1 878
#4 rs2803291 Makrani C T 0.6200000 0 1882185 1 878
#5 rs2803291 Sindhi C T 0.7708330 0 1882185 1 878
#6 rs2803291 Pathan C T 0.6818180 0 1882185 1 878
#7 rs12060022 Brahui T C 0.0600000 1 3108186 1 982
#8 rs12060022 Balochi T C 0.0416667 1 3108186 1 982
#9 rs12060022 Hazara T C 0.0000000 1 3108186 1 982
#10 rs12060022 Makrani T C 0.0200000 1 3108186 1 982
#11 rs12060022 Sindhi T C 0.0625000 1 3108186 1 982
#12 rs12060022 Pathan T C 1.0000000 1 3108186 1 982
#13 rs870171 Brahui T G 0.2200000 0 3332664 1 976
#14 rs870171 Balochi T G 0.3333330 0 3332664 1 976
#15 rs870171 Hazara T G 1.0000000 0 3332664 1 976
#16 rs870171 Makrani T G 1.0000000 0 3332664 1 976
#17 rs870171 Sindhi T G 0.2083330 0 3332664 1 976
#18 rs870171 Pathan T G 1.0000000 0 3332664 1 976
Upvotes: 3