Kelly Williams Kelly Williams - 28 days ago 11
R Question

Replace integers with consecutive natural numbers in two columns

I am using R version 3.1.2 on a Mac (x86_64-apple-darwin13.4.0)

I have 40 files that each have 5 columns as shown below.

> D16S503
MARKER LANE ID A_1 A_2
1 D16S503 D16S503 1228-0198898 309 313
2 D16S503 D16S503 1228-0198899 301 311
3 D16S503 D16S503 1228-0198900 301 311
4 D16S503 D16S503 1228-0198901 301 311
5 D16S503 D16S503 1228-0198903 311 313
6 D16S503 D16S503 1228-0198904 301 301
7 D16S503 D16S503 1228-0198905 301 301
8 D16S503 D16S503 1228-0198906 301 313
9 D16S503 D16S503 1228-0198907 301 311
10 D16S503 D16S503 1228-0198908 301 313
11 D16S503 D16S503 1228-0198909 301 311
12 D16S503 D16S503 1228-0198910 301 301
13 D16S503 D16S503 1228-0198911 301 307
14 D16S503 D16S503 1228-0198912 301 301
15 D16S503 D16S503 1228-0198913 301 311
16 D16S503 D16S503 1228-0198914 301 311
17 D16S503 D16S503 1228-0198915 311 311
18 D16S503 D16S503 1228-0198916 301 311
19 D16S503 D16S503 1228-0198917 311 313
20 D16S503 D16S503 1228-0198918 301 301
21 D16S503 D16S503 1228-0198919 301 313
22 D16S503 D16S503 1228-0198920 301 311
23 D16S503 D16S503 1228-0198921 305 311
24 D16S503 D16S503 1228-0198922 311 311
25 D16S503 D16S503 1228-0198923 307 311
26 D16S503 D16S503 1228-0198924 301 311


First I identify unique integers in the last two columns.

> sort(unique(c(D16S503$A_1,D16S503$A_2)))
[1] 301 305 307 309 311 313


I then wish to replace the integers in columns D16S503$A_1 and D16S503$A_2 with increasing consecutive natural numbers starting from 1.
i.e. replace 301 with 1, 305 with 2, 307 with 3, etc.

Here is my desired data frame

> D16S503
MARKER LANE ID A_1 A_2
1 D16S503 D16S503 1228-0198898 4 6
2 D16S503 D16S503 1228-0198899 1 5
3 D16S503 D16S503 1228-0198900 1 5
4 D16S503 D16S503 1228-0198901 1 5
5 D16S503 D16S503 1228-0198903 5 6
6 D16S503 D16S503 1228-0198904 1 1
7 D16S503 D16S503 1228-0198905 1 1
8 D16S503 D16S503 1228-0198906 1 6
9 D16S503 D16S503 1228-0198907 1 5
10 D16S503 D16S503 1228-0198908 1 6
11 D16S503 D16S503 1228-0198909 1 5
12 D16S503 D16S503 1228-0198910 1 1
13 D16S503 D16S503 1228-0198911 1 3
14 D16S503 D16S503 1228-0198912 1 1
15 D16S503 D16S503 1228-0198913 1 5
16 D16S503 D16S503 1228-0198914 1 5
17 D16S503 D16S503 1228-0198915 5 5
18 D16S503 D16S503 1228-0198916 1 5
19 D16S503 D16S503 1228-0198917 5 6
20 D16S503 D16S503 1228-0198918 1 1
21 D16S503 D16S503 1228-0198919 1 6
22 D16S503 D16S503 1228-0198920 1 5
23 D16S503 D16S503 1228-0198921 2 5
24 D16S503 D16S503 1228-0198922 5 5
25 D16S503 D16S503 1228-0198923 3 5
26 D16S503 D16S503 1228-0198924 1 5


My files all contain different integers in columns A_1 and A_2, and contain anywhere between 2 and 10 unique integers.

How am I able to do this? I am happy to do each file one by one, but I know an R function would be much quicker and less chance for error.

Answer

In R, you could convert the desired columns ("A_1", "A_2") to "factor" class by specifying the "levels" as the sorted concatenated unique elements from those columns ("lvls"), then coerce it back to "numeric".

lvls <- sort(unique(c(D16S503$A_1,D16S503$A_2)))
D16S503[4:5] <- lapply(D16S503[4:5], function(x)
          as.numeric(factor(x, levels=lvls)))

head(D16S503,3)
#   MARKER    LANE           ID A_1 A_2
#1 D16S503 D16S503 1228-0198898   4   6
#2 D16S503 D16S503 1228-0198899   1   5
#3 D16S503 D16S503 1228-0198900   1   5