Filling a table with additional columns if they don't exist - r
I've the following difficult problem. Here short example of my data. Assume that I've two data sets (my real example has something about 20). The data frames result as a list computed by a self written function with lapply. So, I put the data frames in my example in a list, too. Then I "rbind" them to compute a frequency table.
df1 <- data.frame(rev(seq(12:0)), paste0("a=",sample(0:12, 13, replace=T)))
colnames(df1) <- c("k", "a")
df2 <- data.frame(rev(seq(12:0)), paste0("a=",sample(0:12, 13, replace=T)))
colnames(df2) <- c("k", "a")
list_df <- list(df1,df2)
df_combine<- plyr::ldply(list_df, rbind)
freq_foo <- table(df_combine$k,df_combine$a)
I get a frequency table of the following form.
a=0 a=11 a=12 a=2 a=5 a=6 a=7 a=8 a=3 a=9
1 1 0 0 0 0 0 0 1 0 0
2 1 0 0 0 0 0 0 0 0 1
3 1 0 0 0 0 1 0 0 0 0
4 0 0 0 1 0 1 0 0 0 0
5 0 0 0 1 1 0 0 0 0 0
6 0 0 0 0 0 0 1 0 0 1
7 0 1 1 0 0 0 0 0 0 0
8 1 0 0 0 0 1 0 0 0 0
9 0 0 0 0 0 0 2 0 0 0
10 0 0 1 0 1 0 0 0 0 0
11 1 1 0 0 0 0 0 0 0 0
12 0 0 0 0 0 0 1 0 1 0
13 1 0 1 0 0 0 0 0 0 0
I want to extend and manipulate my table in the following way:
First the table should go over a range of a=0 to a=15. So if there is a missing column, it should be added. And 2nd) I want to order the columns from 0 to 15.
For the first problem I tried
if(freq_foo$paste0("a=",0:15) == F){freq_foo$paste("a=",0:15) <- 0}
but this should work only for data frames and not for tables. Also. i've no idea how to order the columns with an ascending order. The data type isnt important to me because I just want to use the output for further calculations. So, it can also be a data frame instead of a table.
#convert freq_foo table to dataframe
df <- as.data.frame.matrix(freq_foo)
#add all zeros column for missing column name in 0:15 series
df[, paste0("a=", c(0:15)[!(c(0:15) %in% as.numeric(gsub(".*=(\\d+)", "\\1", names(df))))])] <- 0
#order columns from 0 to 15
df <- df[, order(as.numeric(gsub(".*=(\\d+)", "\\1", names(df))))]
Output is:
a=0 a=1 a=2 a=3 a=4 a=5 a=6 a=7 a=8 a=9 a=10 a=11 a=12 a=13 a=14 a=15
1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0
2 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0
3 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0
5 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
7 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
8 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
10 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
11 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
12 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0
13 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
(Edit: Updated code after getting a requirement clarification from OP)
Related
Multiplying multiple columns with each other into a new dataframe in R
I want to multiply many of my binary variables into new columns, so called interactive variables. My dataset is structured like this: YearCountry <- data.frame( Time = c("2000","2001", "2002", "2003", "2000","2001", "2002", "2003", "2000","2001", "2002", "2003"), AL = c(1,1,1,1,0,0,0,0,0,0,0,0), FR = c(0,0,0,0,1,1,1,1,0,0,0,0), UK = c(0,0,0,0,0,0,0,0,1,1,1,1), Y2000d = c(1,0,0,0,1,0,0,0,1,0,0,0), Y2001d = c(0,1,0,0,0,1,0,0,0,1,0,0), Y2002d = c(0,0,1,0,0,0,1,0,0,0,1,0), Y2003d = c(0,0,0,1,0,0,0,1,0,0,0,1)) YearCountry Time AL FR UK Y2000d Y2001d Y2002d Y2003d 1 2000 1 0 0 1 0 0 0 2 2001 1 0 0 0 1 0 0 3 2002 1 0 0 0 0 1 0 4 2003 1 0 0 0 0 0 1 5 2000 0 1 0 1 0 0 0 6 2001 0 1 0 0 1 0 0 7 2002 0 1 0 0 0 1 0 8 2003 0 1 0 0 0 0 1 9 2000 0 0 1 1 0 0 0 10 2001 0 0 1 0 1 0 0 11 2002 0 0 1 0 0 1 0 12 2003 0 0 1 0 0 0 1 I need to multiply the binary variable for each of the countries (AL,FR,UK) with each of the binary variables for a given year so that I get #country x #year new variables. In this case I have three countries and four years which gives 12 new variables. My full data contains 105 countries/regions and stretches over twenty years. I therefore need a general formula. I want data that looks like this Interact <- data.frame(Time = c("2000","2001", "2002", "2003", "2000","2001", "2002", "2003", "2000","2001", "2002", "2003"), Y2000xAL = c(1,0,0,0,0,0,0,0,0,0,0,0), Y2001xAL = c(0,1,0,0,0,0,0,0,0,0,0,0), Y2002xAL = c(0,0,1,0,0,0,0,0,0,0,0,0), Y2003xAL = c(0,0,0,1,0,0,0,0,0,0,0,0), Y2000xFR = c(0,0,0,0,1,0,0,0,0,0,0,0), Y2001xFR = c(0,0,0,0,0,1,0,0,0,0,0,0), Y2002xFR = c(0,0,0,0,0,0,1,0,0,0,0,0), Y2003xFR = c(0,0,0,0,0,0,0,1,0,0,0,0), Y2000xUk = c(0,0,0,0,0,0,0,0,1,0,0,0), Y2001xUK = c(0,0,0,0,0,0,0,0,0,1,0,0), Y2002xUK = c(0,0,0,0,0,0,0,0,0,0,1,0), Y2003xUK = c(0,0,0,0,0,0,0,0,0,0,0,1)) Interact Time Y2000xAL Y2001xAL Y2002xAL Y2003xAL Y2000xFR Y2001xFR Y2002xFR Y2003xFR Y2000xUk Y2001xUK Y2002xUK Y2003xUK 1 2000 1 0 0 0 0 0 0 0 0 0 0 0 2 2001 0 1 0 0 0 0 0 0 0 0 0 0 3 2002 0 0 1 0 0 0 0 0 0 0 0 0 4 2003 0 0 0 1 0 0 0 0 0 0 0 0 5 2000 0 0 0 0 1 0 0 0 0 0 0 0 6 2001 0 0 0 0 0 1 0 0 0 0 0 0 7 2002 0 0 0 0 0 0 1 0 0 0 0 0 8 2003 0 0 0 0 0 0 0 1 0 0 0 0 9 2000 0 0 0 0 0 0 0 0 1 0 0 0 10 2001 0 0 0 0 0 0 0 0 0 1 0 0 11 2002 0 0 0 0 0 0 0 0 0 0 1 0 12 2003 0 0 0 0 0 0 0 0 0 0 0 1
Here's an approach with dplyr::across. We can make the final result into a plain data.frame with purrr:invoke as demonstrated in this answer. library(dplyr) library(purrr) YearCountry %>% mutate(across(AL:UK, ~ . * select(cur_data(), Y2000d:Y2003d))) %>% select(-(Y2000d:Y2003d)) %>% invoke(.f = data.frame) %>% rename_with(~str_replace(.,"\\.","")) Time ALY2000d ALY2001d ALY2002d ALY2003d FRY2000d FRY2001d FRY2002d FRY2003d UKY2000d UKY2001d UKY2002d UKY2003d 1 2000 1 0 0 0 0 0 0 0 0 0 0 0 2 2001 0 1 0 0 0 0 0 0 0 0 0 0 3 2002 0 0 1 0 0 0 0 0 0 0 0 0 4 2003 0 0 0 1 0 0 0 0 0 0 0 0 5 2000 0 0 0 0 1 0 0 0 0 0 0 0 6 2001 0 0 0 0 0 1 0 0 0 0 0 0 7 2002 0 0 0 0 0 0 1 0 0 0 0 0 8 2003 0 0 0 0 0 0 0 1 0 0 0 0 9 2000 0 0 0 0 0 0 0 0 1 0 0 0 10 2001 0 0 0 0 0 0 0 0 0 1 0 0 11 2002 0 0 0 0 0 0 0 0 0 0 1 0 12 2003 0 0 0 0 0 0 0 0 0 0 0 1
1) model.matrix We split the names by the number of characters in them (the countries have 2 characters in their names and the years have 6) and paste pluses in each. (Alternately use Plus(grep("^..$", nms, value = TRUE)) to get the country names and use that in place of spl["2"] and similarly Plus(grep("^Y....d$", nms, value = TRUE)) in place of spl["6"].) c(`2` = "AL+FR+UK", `6` = "Y2000d+Y2001d+Y2002d+Y2003d") and from that the formula: ~(AL + FR + UK):(Y2000d + Y2001d + Y2002d + Y2003d) + 0 and then compute its model matrix. The formula could also be expanded to one accepted by lm by modifying the sprintf format so we might not even need to create the model matrix. For example, if we had a response vector R then we could write: s <- sprintf("R ~ (%s)*(%s)", spl["2"], spl["4"]); fo <- formula(s); lm(fo, YearCountry) to include all variables and the interactions of countries and year as well as an intercept. Plus <- function(x) paste(x, collapse = "+") nms <- names(YearCountry)[-1] spl <- sapply(split(nms, nchar(nms)), Plus) s <- sprintf("~ (%s):(%s)+0", spl["2"], spl["6"]) fo <- formula(s) model.matrix(fo, YearCountry) giving this matrix: AL:Y2000d AL:Y2001d AL:Y2002d AL:Y2003d FR:Y2000d FR:Y2001d FR:Y2002d FR:Y2003d UK:Y2000d UK:Y2001d UK:Y2002d UK:Y2003d 1 1 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 3 0 0 1 0 0 0 0 0 0 0 0 0 4 0 0 0 1 0 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 0 0 0 0 6 0 0 0 0 0 1 0 0 0 0 0 0 7 0 0 0 0 0 0 1 0 0 0 0 0 8 0 0 0 0 0 0 0 1 0 0 0 0 9 0 0 0 0 0 0 0 0 1 0 0 0 10 0 0 0 0 0 0 0 0 0 1 0 0 11 0 0 0 0 0 0 0 0 0 0 1 0 12 0 0 0 0 0 0 0 0 0 0 0 1 attr(,"assign") [1] 1 2 3 4 5 6 7 8 9 10 11 12 Alternately we can write it compactly like this: Plus <- function(x) paste(x, collapse = "+") nms <- names(YearCountry) s <- sprintf("~ (%s):(%s)+0", Plus(nms[2:4]), Plus(nms[5:8])) fo <- formula(s) model.matrix(fo, YearCountry) 2) eList Another approach is to use list comprehensions. With the eList package we can do this: library(eList) DF(for(i in YearCountry[2:4]) for(j in YearCountry[5:8]) i*j) giving this data frame. Use as.matrix(...) on it if you want a matrix. AL.Y2000d AL.Y2001d AL.Y2002d AL.Y2003d FR.Y2000d FR.Y2001d FR.Y2002d FR.Y2003d UK.Y2000d UK.Y2001d UK.Y2002d UK.Y2003d 1 1 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 3 0 0 1 0 0 0 0 0 0 0 0 0 4 0 0 0 1 0 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 0 0 0 0 6 0 0 0 0 0 1 0 0 0 0 0 0 7 0 0 0 0 0 0 1 0 0 0 0 0 8 0 0 0 0 0 0 0 1 0 0 0 0 9 0 0 0 0 0 0 0 0 1 0 0 0 10 0 0 0 0 0 0 0 0 0 1 0 0 11 0 0 0 0 0 0 0 0 0 0 1 0 12 0 0 0 0 0 0 0 0 0 0 0 1 3) listcompr listcompr is another list comprehension package. Note that the development version of this package is needed in order to use bycol=. Replace gen.named.matrix with gen.named.data.frame if you want a data frame. # devtools::github_github("patrickroocks/listcompr") library(listcompr) nms <- names(YearCountry) gen.named.matrix("{nms[i]}.{nms[j]}", YearCountry[[i]] * YearCountry[[j]], i = 2:4, j = 5:8, bycol = TRUE)
R multiple for loop
I have this loop over the file msp.chr1 for(i in names(msp.chr1[c(7:70)])){ tmp <- rle(msp.chr1[[i]])$lengths msp.chr1$idx <- rep(1:length(tmp),tmp) tmp2 <- unlist(by(msp.chr1[msp.chr1[[i]]==1,], list(msp.chr1$idx[msp.chr1[[i]]==1]),function(x){tail(x["epos"],1)-head(x["spos"],1)})) assign(paste(i, ".chr1", sep=""), as.vector(tmp2)) rm(i); rm(tmp); rm(tmp2) } This file is a dataframe with multiple columns: head(msp.chr1) chm spos epos sgpos egpos nsnps PDAC1.0 PDAC1.1 PDAC10.0 PDAC10.1 PDAC100.0 PDAC100.1 PDAC101.0 PDAC101.1 PDAC102.0 PDAC102.1 PDAC103.0 PDAC103.1 1 1 123492 134160 0.12 0.13 252 0 0 0 0 1 0 0 0 0 0 0 0 2 1 134160 135025 0.13 0.14 20 0 0 0 0 1 0 0 0 0 0 0 0 3 1 135025 145600 0.14 0.15 150 0 0 0 0 1 0 0 0 0 0 0 0 4 1 145600 316603 0.15 0.32 195 0 1 0 0 1 0 0 1 0 0 0 1 5 1 316603 520140 0.32 0.52 765 0 0 0 0 0 0 0 0 0 0 0 0 6 1 520140 667054 0.52 0.67 1080 0 0 0 0 0 0 0 0 0 0 0 0 PDAC104.0 PDAC104.1 PDAC105.0 PDAC105.1 PDAC11.0 PDAC11.1 PDAC12.0 PDAC12.1 PDAC13.0 PDAC13.1 PDAC14.0 PDAC14.1 PDAC15.0 PDAC15.1 PDAC17.0 PDAC17.1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 PDAC18.0 PDAC18.1 PDAC19.0 PDAC19.1 PDAC2.0 PDAC2.1 PDAC20.0 PDAC20.1 PDAC21.0 PDAC21.1 PDAC22.0 PDAC22.1 PDAC23.0 PDAC23.1 PDAC24.0 PDAC24.1 PDAC25.0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 3 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 4 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 PDAC25.1 PDAC3.0 PDAC3.1 PDAC4.0 PDAC4.1 PDAC5.0 PDAC5.1 PDAC6.0 PDAC6.1 PDAC7.0 PDAC7.1 PDAC8.0 PDAC8.1 PDAC807.0 PDAC807.1 PDAC810.0 PDAC810.1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 PDAC9.0 PDAC9.1 idx 1 0 0 1 2 0 0 1 3 0 0 1 4 0 0 1 5 1 0 1 6 1 0 1 for(i in names(msp.chr1[c(7:70)])){ tmp <- rle(msp.chr1[[i]])$lengths msp.chr1$idx <- rep(1:length(tmp),tmp) tmp2 <- unlist(by(msp.chr1[msp.chr1[[i]]==1,], list(msp.chr1$idx[msp.chr1[[i]]==1]),function(x){tail(x["epos"],1)-head(x["spos"],1)})) assign(paste(i, ".chr1", sep=""), as.vector(tmp2)) rm(i); rm(tmp); rm(tmp2) } But I actually have 23 files, of names msp.chr1, msp.chr2, ..., msp.chr23. I want to add another loop on the above, to do that on all files at once. I tried several things but it is not working... Basically, every chr1 in my loop (including in the assign) should be replaced by chr1 to chr23. Can you help? Thanks,
You can generate the name of the file with paste, and then get the file by its name with get. A better option would be to create these files within a list, then you'd only use the j like df=list[[j]]. for(j in 1:23){ df = get(paste("msp.chr",j,sep="")) for(i in names(df[c(7:70)])){ tmp <- rle(df[[i]])$lengths df$idx <- rep(1:length(tmp),tmp) tmp2 <- unlist(by(df[df[[i]]==1,], list(df$idx[df[[i]]==1]),function(x){tail(x["epos"],1)-head(x["spos"],1)})) assign(paste(i, ".chr1", sep=""), as.vector(tmp2)) rm(i); rm(tmp); rm(tmp2) } }
creating a larger matrix from smaller matrices in R
I have a series of text files in a folder called "Disintegration T1" which look like this: > 1.txt 0 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 1 1 0 > 2.txt 0 1 1 0 1 0 0 1 1 1 1 1 0 1 1 1 1 1 0 1 0 0 0 0 1 > 3.txt 0 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 The files are all either 4X4 or 5X5. They must be read in as matrices, as the data is for social network analyses. My goal is to automate the process of putting these matrices into a larger matrix, so that these matrices are directly diagonal to each other, and 0s inputted in the blank spaces within the larger matrix. In this case the final result would look like: > mega_matrix 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 Thank you!
You want bdiag from the Matrix package: library(Matrix) bdiag(matrix1, matrix2, matrix3) And to do the whole directory (thanks to #user20650 in the comments) : bdiag(lapply(dir(), function(x){as.matrix(read.table(x))}))
using lappy and elseif command
Using R I have a table, lets say 'locations' head(locations, n=10) apillar fender fwheel fdoor compart rdoor rwheel boot 1 0 0 0 0 0 0 0 1 2 0 0 0 1 0 0 0 0 3 0 0 0 0 1 0 0 0 4 0 1 0 0 0 0 0 0 5 1 0 1 0 0 0 0 0 6 1 0 0 1 0 0 0 0 7 0 0 0 0 0 0 0 0 8 0 0 0 0 1 0 0 0 9 0 0 0 1 0 0 0 0 10 0 0 0 0 0 1 0 0 now i want to create a new variable "cat" which groups the impacts into category locations. I have been using if, elseif and else command, but I cannot get it to work. The command is: cat <- lapply(locations, function(x) if (apillar|fender|fwheel == 1)print("front") else if (fdoor|compart|rdoor == 1)print("middle") else if(rwheel|boot ==1)print("rear") else print("NA") such that cat should read rear, middle, middle, middle, front etc
When vectors of TRUE or FALSE statements are involved, I usually prefer not to work with if to avoid loops. I find conditional referencing to be more elegant in this case. See below. locations <- read.table(header=TRUE, text= "apillar fender fwheel fdoor compart rdoor rwheel boot 1 0 0 0 0 0 0 0 1 2 0 0 0 1 0 0 0 0 3 0 0 0 0 1 0 0 0 4 0 1 0 0 0 0 0 0 5 1 0 1 0 0 0 0 0 6 1 0 0 1 0 0 0 0 7 0 0 0 0 0 0 0 0 8 0 0 0 0 1 0 0 0 9 0 0 0 1 0 0 0 0 10 0 0 0 0 0 1 0 0") locations$cat <- NA within(locations,{ cat[apillar|fender|fwheel] <- "front" cat[fdoor|compart|rdoor] <- "middle" cat[rwheel|boot] <- "rear" }) Result: apillar fender fwheel fdoor compart rdoor rwheel boot cat 1 0 0 0 0 0 0 0 1 rear 2 0 0 0 1 0 0 0 0 middle 3 0 0 0 0 1 0 0 0 middle 4 0 1 0 0 0 0 0 0 front 5 1 0 1 0 0 0 0 0 front 6 1 0 0 1 0 0 0 0 middle 7 0 0 0 0 0 0 0 0 <NA> 8 0 0 0 0 1 0 0 0 middle 9 0 0 0 1 0 0 0 0 middle 10 0 0 0 0 0 1 0 0 middle Cheers!
Corrected your own code: locations$cat= with(locations, ifelse(apillar|fender|fwheel, "front", ifelse(fdoor|compart|rdoor,"middle",ifelse(rwheel|boot, "rear", "NA"))) ) > locations apillar fender fwheel fdoor compart rdoor rwheel boot cat 1 0 0 0 0 0 0 0 1 rear 2 0 0 0 1 0 0 0 0 middle 3 0 0 0 0 1 0 0 0 middle 4 0 1 0 0 0 0 0 0 front 5 1 0 1 0 0 0 0 0 front 6 1 0 0 1 0 0 0 0 front 7 0 0 0 0 0 0 0 0 NA 8 0 0 0 0 1 0 0 0 middle 9 0 0 0 1 0 0 0 0 middle 10 0 0 0 0 0 1 0 0 middle >
For loop in a data table with dependencies in R?
I want to update the following datatable: DT1: (This datatable columns values I need to edit based on my input) BIC BCC1 BCC2 BCC6 BCC8 BCC9 BCC10 BCC11 990081899A 0 1 0 0 0 0 0 9900023620 0 1 1 0 0 0 0 9900427160 0 1 0 0 0 0 0 990064457TA 1 1 0 0 0 0 0 990066595A 0 0 0 1 0 0 1 990088248A 0 0 0 1 0 0 1 990088882C1 0 0 0 1 0 0 1 990088882C2 0 0 0 1 1 0 0 990088882C3 0 0 0 1 1 0 1 990088882C4 0 0 0 0 1 0 1 990088882C5 0 0 0 0 1 0 1 I want to loop through DT1 column names except first column to check if my input and any of the column names are equal. If they are equal, then check through all the rows of that column if the value is equal to 1. If yes, then set some of the other column values of that row equals to 0. I am doing this now: >Hierarchy <- function(Dt, cc, Hier){ Dt_cols<-setdiff(names(Dt), "HIC") Dt_rows<-1:nrow(Dt) for(j in 1:length(Dt_cols)){ if(Dt_cols[j] == cc){ for(i in 1:length(Dt_rows)){ if(eval(parse(text = paste("Dt[",i,",",eval(Dt_cols[j]),"]"))) == 1){ for(k in 1:length(Hier)){ if(Dt_cols[j] == Hier[k]){ hierVar<-as.character(eval(Dt_cols[j])); Dt[i,hierVar]<- 0 }}}}}}return(Dt)} If I am passing following arguments to this function: >Hierarchy(DT1,"BCC8", c("BCC9","BCC10","BCC11","BCC12")) Result should be: BIC BCC1 BCC2 BCC6 BCC8 BCC9 BCC10 BCC11 990081899A 0 1 0 0 0 0 0 9900023620 0 1 1 0 0 0 0 9900427160 0 1 0 0 0 0 0 990064457TA 1 1 0 0 0 0 0 990066595A 0 0 0 1 0 0 0 990088248A 0 0 0 1 0 0 0 990088882C1 0 0 0 1 0 0 0 990088882C2 0 0 0 1 0 0 0 990088882C3 0 0 0 1 0 0 0 990088882C4 0 0 0 0 1 0 0 990088882C5 0 0 0 0 1 0 0 But with this function is not working properly. I am not able to find another way or correct way of doing. Any suggestions are appreciated. Thanks!