Bug in R with subset - r
I have some trouble while trying to get a subset of an initial dataframe as in the end it corrupts my dataframe! Here is an example of what is happening:
Let consider a dataframe :
>test=data.frame("v1"=c(1,2,3,4,-5,-3),"v2"=c(1,2,3,4,5,6))
> print(test)
v1 v2
1 1 1
2 2 2
3 3 3
4 4 4
5 -5 5
6 -3 6
Then I want to take the subset where var1 value is strictly below, let's say -2:
> subtest=test[test$v1<-2,]
> print(subtest)
v1 v2
2 2 2
> print(test)
v1 v2
1 2 1
2 2 2
3 2 3
4 2 4
5 2 5
6 2 6
Not only did the subset operation didn't work but it actually corrupt my initial database by replacing all the v1 values by 2 !
I t is not a bug. It is just a typo!
The operator <- is used to assign values. In the command subtest=test[test$v1<-2,], you have assigned all values of variable v1 to 2.
To do what you want, you should do that instead:
subtest=test[test$v1< -2,]
It is not a bug. You just have to put brackets, because otherwise it will be assignment mark <-. If you want strictly below -2:
subtest=test[test$v1<(-2),]
Related
runner:streak_run shows unexpected result when k remains unchanged
I'm using runner:streak_run to count sequences of 0 and 1 in a column called "inactive_indicator". The column is= 0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1 For runner::streak_run(inactive_indicator)) I get the following: 1,2,3,1,2,3,1,1,2,1,2,3,4,5,5,5,5,1,2,3,4 Why is it stuck on 5 when it should go up to 8? In documentation it says that k - running window size. By default window size equals length(x). Allow varying window size specified by vector of length(x) As I understand, the default definition should be enough. Problem resolves and I get expected results when running: runner::streak_run(inactive_indicator),k=length(inactive_indicator)) Why doesn't it work in the first place?
This can be solved with rle from base R sequence(rle(inactive_indicator)$lengths) #[1] 1 2 3 1 2 3 1 1 2 1 2 3 4 5 6 7 8 1 2 3 4 Checked with runner runner::streak_run(inactive_indicator) #[1] 1 2 3 1 2 3 1 1 2 1 2 3 4 5 6 7 8 1 2 3 4 It is possible that there are some leading/lagging spaces in the column and it is not numeric. In that case, use trimws runner::streak_run(trimws(inactive_indicator)) data inactive_indicator <- c(0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1)
Removing character from dataframe
I have this simple code, which generates a data frame. I want to remove the V character from the middle column. Is there any simple way to do that? Here is a test code (the actual code is very long), very similar with the actual code. mat1=matrix(c(1,2,3,4,5,"V1","V2","V3","V4","V5",1,2,3,4,5), ncol=3) mat=as.data.frame(mat1) colnames(mat)=c("x","row","y") mat This is the data frame: x row y 1 1 V1 1 2 2 V2 2 3 3 V3 3 4 4 V4 4 5 5 V5 5 I just want to remove the V's like this: x row y 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
We can use str_replace from stringr library(stringr) mat$row <- str_replace(mat$row, "V", "")
How to BiCluster with constant values in columns - in R
My Problem in general: I have a data frame where i would like to find all bi-clusters with constant values in columns. For Example the initial dataframe: > df v1 v2 v3 1 0 2 1 2 1 3 2 3 2 4 3 4 3 3 4 5 4 2 3 6 5 2 4 7 2 2 3 8 3 1 2 And for example i would like to find the a cluster like this: > cluster1 v1 v3 1 2 3 2 2 3 I tried to use the biclust package and tested several functions but the result was always not what i want to archive. I figured out that I may can use the BCPlaid function with fit.model = y ~ m. But it looks like this produce also different results. Is there a way to archive this task efficient?
Divide each rows by a different number
I've looked on the internet but I haven found the answer that I'm looking for, but shure it's out there... I've a data frame, and I want to divide (or any other operation) every cell of a row by a value that it's placed in the second column of my data frame. So first row from col3 to last col, divide each cell by the value of col2 of that certain row, and so on for every single row. I have solved this by using a For loop, col2 (delta) it's now a vector, and col3 to end it's a data.frame (mu). The results are append to a new data frame by using rbind. The question is; I'm pretty sure that this can be done by using the function apply, sapply or similar, but I have not gotten the results that I've been looking so far (not the good ones as I do with the loop for). ¿How can I do it without using a loop for? Loop for I've been using so far. In resume. I want to divide each mu by the delta value of it's own row. for (i in 1:(dim(mu)[1])){ RA_row <- mu[i,]/delta[i] RA <- rbind(RA, RA_row) } transcript delta mu_5 mu_15 mu_25 mu_35 mu_45 mu_55 mu_65 1 YAL001C 0.066702720 2.201787e-01 1.175731e-01 2.372506e-01 0.139281317 0.081723456 1.835414e-01 1.678318e-01 2 YAL002W 0.106000180 3.685822e-01 1.326865e-01 2.887973e-01 0.158207858 0.193476082 1.867039e-01 1.776946e-01 3 YAL003W 0.022119345 2.271518e+00 2.390637e+00 1.651997e+00 3.802739732 2.733559839 2.772454e+00 3.571712e+00 Thanks
It appears as though you want just: mu2 <- mu[-(1:2)]/mu[[2]] # same as mu[-(1:2), ]/mu[['delta']] That should produce a new dataframe with the division by row. Somewhat more dangerous would be to do the division "in place". mu[-(1:2)] <- mu[-(1:2)]/mu[[2]] > mu <- data.frame(a=1,b=1:10, c=rnorm(10), d=rnorm(10) ) > mu a b c d 1 1 1 -1.91435943 0.45018710 2 1 2 1.17658331 -0.01855983 3 1 3 -1.66497244 -0.31806837 4 1 4 -0.46353040 -0.92936215 5 1 5 -1.11592011 -1.48746031 6 1 6 -0.75081900 -1.07519230 7 1 7 2.08716655 1.00002880 8 1 8 0.01739562 -0.62126669 9 1 9 -1.28630053 -1.38442685 10 1 10 -1.64060553 1.86929062 > (mu2 <- mu[-(1:2)]/mu[[2]]) c d 1 -1.914359426 0.450187101 2 0.588291656 -0.009279916 3 -0.554990812 -0.106022792 4 -0.115882600 -0.232340537 5 -0.223184021 -0.297492062 6 -0.125136500 -0.179198716 7 0.298166649 0.142861258 8 0.002174452 -0.077658337 9 -0.142922281 -0.153825205 10 -0.164060553 0.186929062 > (mu[-(1:2)] <- mu[-(1:2)]/mu[[2]] ) > mu a b c d 1 1 1 -1.914359426 0.450187101 2 1 2 0.588291656 -0.009279916 3 1 3 -0.554990812 -0.106022792 4 1 4 -0.115882600 -0.232340537 5 1 5 -0.223184021 -0.297492062 6 1 6 -0.125136500 -0.179198716 7 1 7 0.298166649 0.142861258 8 1 8 0.002174452 -0.077658337 9 1 9 -0.142922281 -0.153825205 10 1 10 -0.164060553 0.186929062
Calculating the occurrences of numbers in the subsets of a data.frame
I have a data frame in R which is similar to the follows. Actually my real ’df’ dataframe is much bigger than this one here but I really do not want to confuse anybody so that is why I try to simplify things as much as possible. So here’s the data frame. id <-c(1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3) a <-c(3,1,3,3,1,3,3,3,3,1,3,2,1,2,1,3,3,2,1,1,1,3,1,3,3,3,2,1,1,3) b <-c(3,2,1,1,1,1,1,1,1,1,1,2,1,3,2,1,1,1,2,1,3,1,2,2,1,3,3,2,3,2) c <-c(1,3,2,3,2,1,2,3,3,2,2,3,1,2,3,3,3,1,1,2,3,3,1,2,2,3,2,2,3,2) d <-c(3,3,3,1,3,2,2,1,2,3,2,2,2,1,3,1,2,2,3,2,3,2,3,2,1,1,1,1,1,2) e <-c(2,3,1,2,1,2,3,3,1,1,2,1,1,3,3,2,1,1,3,3,2,2,3,3,3,2,3,2,1,3) df <-data.frame(id,a,b,c,d,e) df Basically what I would like to do is to get the occurrences of numbers for each column (a,b,c,d,e) and for each id group (1,2,3) (for this latter grouping see my column ’id’). So, for column ’a’ and for id number ’1’ (for the latter see column ’id’) the code would be something like this: as.numeric(table(df[1:10,2])) ##The results are: [1] 3 7 Just to briefly explain my results: in column ’a’ (and regarding only those records which have number ’1’ in column ’id’) we can say that number '1' occured 3 times and number '3' occured 7 times. Again, just to show you another example. For column ’a’ and for id number ’2’ (for the latter grouping see again column ’id’): as.numeric(table(df[11:20,2])) ##After running the codes the results are: [1] 4 3 3 Let me explain a little again: in column ’a’ and regarding only those observations which have number ’2’ in column ’id’) we can say that number '1' occured 4 times, number '2' occured 3 times and number '3' occured 3 times. So this is what I would like to do. Calculating the occurrences of numbers for each custom-defined subsets (and then collecting these values into a data frame). I know it is not a difficult task but the PROBLEM is that I’m gonna have to change the input ’df’ dataframe on a regular basis and hence both the overall number of rows and columns might change over time… What I have done so far is that I have separated the ’df’ dataframe by columns, like this: for (z in (2:ncol(df))) assign(paste("df",z,sep="."),df[,z]) So df.2 will refer to df$a, df.3 will equal df$b, df.4 will equal df$c etc. But I’m really stuck now and I don’t know how to move forward… Is there a proper, ”automatic” way to solve this problem?
How about - > library(reshape) > dftab <- table(melt(df,'id')) > dftab , , value = 1 variable id a b c d e 1 3 8 2 2 4 2 4 6 3 2 4 3 4 2 1 5 1 , , value = 2 variable id a b c d e 1 0 1 4 3 3 2 3 3 3 6 2 3 1 4 5 3 4 , , value = 3 variable id a b c d e 1 7 1 4 5 3 2 3 1 4 2 4 3 5 4 4 2 5 So to get the number of '3's in column 'a' and group '1' you could just do > dftab[3,'a',1] [1] 4
A combination of tapply and apply can create the data you want: tapply(df$id,df$id,function(x) apply(df[id==x,-1],2,table)) However, when a grouping doesn't have all the elements in it, as in 1a, the result will be a list for that id group rather than a nice table (matrix). $`1` $`1`$a 1 3 3 7 $`1`$b 1 2 3 8 1 1 $`1`$c 1 2 3 2 4 4 $`1`$d 1 2 3 2 3 5 $`1`$e 1 2 3 4 3 3 $`2` a b c d e 1 4 6 3 2 4 2 3 3 3 6 2 3 3 1 4 2 4 $`3` a b c d e 1 4 2 1 5 1 2 1 4 5 3 4 3 5 4 4 2 5
I'm sure someone will have a more elegant solution than this, but you can cobble it together with a simple function and dlply from the plyr package. ColTables <- function(df) { counts <- list() for(a in names(df)[names(df) != "id"]) { counts[[a]] <- table(df[a]) } return(counts) } results <- dlply(df, "id", ColTables) This gets you back a list - the first "layer" of the list will be the id variable; the second the table results for each column for that id variable. For example: > results[['2']]['a'] $a 1 2 3 4 3 3 For id variable = 2, column = a, per your above example.
A way to do it is using the aggregate function, but you have to add a column to your dataframe > df$freq <- 0 > aggregate(freq~a+id,df,length) a id freq 1 1 1 3 2 3 1 7 3 1 2 4 4 2 2 3 5 3 2 3 6 1 3 4 7 2 3 1 8 3 3 5 Of course you can write a function to do it, so it's easier to do it frequently, and you don't have to add a column to your actual data frame > frequency <- function(df,groups) { + relevant <- df[,groups] + relevant$freq <- 0 + aggregate(freq~.,relevant,length) + } > frequency(df,c("b","id")) b id freq 1 1 1 8 2 2 1 1 3 3 1 1 4 1 2 6 5 2 2 3 6 3 2 1 7 1 3 2 8 2 3 4 9 3 3 4
You didn't say how you'd like the data. The by function might give you the output you like. by(df, df$id, function(x) lapply(x[,-1], table))