Column-wise subset of data frame in R - r

I need some help with subset/filter of data.frame. Below is the code for my random dataset.
A <- c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4)
B <- c(3,3,3,3,4,4,4,4,1,1,1,1,2,2,2,2)
C <- c(1,1,1,1,3,3,3,3,2,2,2,2,4,4,4,4)
Fakey <- data.frame(A, B, C)
Filter_Fakey <- subset(Fakey, (Fakey>1 & Fakey<4))
That last line of coode results in the following:
> Filter_Fakey
A B C
5 2 4 3
6 2 4 3
7 2 4 3
8 2 4 3
9 3 1 2
10 3 1 2
11 3 1 2
12 3 1 2
NA NA NA NA
NA.1 NA NA NA
NA.2 NA NA NA
NA.3 NA NA NA
NA.4 NA NA NA
NA.5 NA NA NA
NA.6 NA NA NA
NA.7 NA NA NA
NA.8 NA NA NA
NA.9 NA NA NA
NA.10 NA NA NA
NA.11 NA NA NA
NA.12 NA NA NA
NA.13 NA NA NA
NA.14 NA NA NA
NA.15 NA NA NA
But What I really want is this,
> Filter_Fakey
A B C
5 2 3 3
6 2 3 3
7 2 3 3
8 2 3 3
9 3 2 2
10 3 2 2
11 3 2 2
12 3 2 2
NA NA NA NA
NA.1 NA NA NA
NA.2 NA NA NA
NA.3 NA NA NA
NA.4 NA NA NA
NA.5 NA NA NA
NA.6 NA NA NA
NA.7 NA NA NA
NA.8 NA NA NA
NA.9 NA NA NA
NA.10 NA NA NA
NA.11 NA NA NA
NA.12 NA NA NA
NA.13 NA NA NA
NA.14 NA NA NA
NA.15 NA NA NA
I've tried subset(), subset(with a negation condition), filter{dplyr}, and the different bracket notations ('[' and '[['). Thanks for helping me out.

Use lapply to loop through columns of the data frame, and set values out of conditions to be NA if that is what you are after. Use order(is.na(...)) to arrange NA values to the last positions:
do.call(cbind, lapply(Fakey, function(col) {
col[col <= 1 | col >= 4] <- NA; col[order(is.na(col))]
}))
A B C
1 2 3 3
2 2 3 3
3 2 3 3
4 2 3 3
5 3 2 2
6 3 2 2
7 3 2 2
8 3 2 2
9 NA NA NA
10 NA NA NA
11 NA NA NA
12 NA NA NA
13 NA NA NA
14 NA NA NA
15 NA NA NA
16 NA NA NA

Another option is using length<- to pad NA at the end after subsetting each of the columns using the logical condition.
data.frame(lapply(Fakey, function(x) `length<-`(x[x > 1 & x <4], nrow(Fakey))))
# A B C
#1 2 3 3
#2 2 3 3
#3 2 3 3
#4 2 3 3
#5 3 2 2
#6 3 2 2
#7 3 2 2
#8 3 2 2
#9 NA NA NA
#10 NA NA NA
#11 NA NA NA
#12 NA NA NA
#13 NA NA NA
#14 NA NA NA
#15 NA NA NA
#16 NA NA NA

Related

Combining variables in r

I've got a dataset like the following.
df <- read.table(header=TRUE, text="
T_A_01_F_1 T_A_02_F_1 T_A_03_F_1 T_A_01_F_2 T_A_02_F_2 T_A_03_F_2 T_A_01_U_1 T_A_02_U_1 T_A_03_U_1 T_A_01_U_2 T_A_02_U_2 T_A_03_U_2 T_B_01_F_1 T_B_02_F_1 T_B_03_F_1 T_B_01_F_2 T_B_02_F_2 T_B_03_F_2 T_B_01_U_1 T_B_02_U_1 T_B_03_U_1 T_B_01_U_2 T_B_02_U_2 T_B_03_U_2
1 2 3 NA NA NA 2 2 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2 2 5 NA NA NA 1 3 3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
5 3 3 NA NA NA 2 1 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2 4 5 NA NA NA 6 3 4 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
NA NA NA 4 3 5 NA NA NA 4 3 2 NA NA NA NA NA NA NA NA NA NA NA NA
NA NA NA 4 4 5 NA NA NA 2 1 1 NA NA NA NA NA NA NA NA NA NA NA NA
NA NA NA 3 1 4 NA NA NA 2 1 7 NA NA NA NA NA NA NA NA NA NA NA NA
NA NA NA 2 1 6 NA NA NA 3 3 6 NA NA NA NA NA NA NA NA NA NA NA NA
NA NA NA NA NA NA NA NA NA NA NA NA 1 1 1 NA NA NA 2 3 1 NA NA NA
NA NA NA NA NA NA NA NA NA NA NA NA 2 1 1 NA NA NA 3 2 2 NA NA NA
NA NA NA NA NA NA NA NA NA NA NA NA 3 2 1 NA NA NA 4 2 1 NA NA NA
NA NA NA NA NA NA NA NA NA NA NA NA 2 5 4 NA NA NA 6 1 4 NA NA NA
NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 3 2 2 NA NA NA 1 2 5
NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 5 4 4 NA NA NA 3 3 5
NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 5 4 4 NA NA NA 1 3 5
NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 5 1 3 NA NA NA 7 5 1
")
In this case its a 2x2x2 mixed design with "T" being the variable of interest with 3 items, "A" and "B" the between factor, "F" and "U" the within factor and "1" and "2" the between factor. I'd like to reduce the dataset, so that I can compute a cronbachs alpha.
As every Person either got A or B and either 1 or 2 I'd like to combine those items, so that I only have the items T_01_F, T_01_U, T_02_F, T_02_U, T_03_F, T_03_U
I could do this by hand, but does somebody know a quick command with which I could do that?
Thank you so much in advance!!
best, Nash
Perhaps a combination of pivot_longer() and separate() might work since all your column names appear to share the same structure.
library(tidyverse)
df<- df %>%
rownames_to_column() %>%
pivot_longer(cols = T_A_01_F_1:T_B_03_U_2) %>%
separate(col = name, sep = "_", into = c("t", "a_b", "number" , "within", "between"))

R data.table: changing the value of a variable over a specific number of dates conditionally

I have a data set in which I'm tracking the dates a patient has specific symptoms
The data set looks like the following :
ID Date symp wt ht sympTY sympDays
1 1/05/2012 NA NA NA NA NA
1 1/06/2012 NA NA NA NA NA
1 1/07/2012 NA NA NA NA NA
1 1/08/2012 NA NA NA NA NA
1 1/09/2012 NA NA NA NA NA
1 1/10/2012 NA NA NA NA NA
1 1/11/2012 1 23 15 1 3
1 1/23/2015 NA 27 19 NA NA
2 2/17/2014 NA NA NA NA NA
2 2/18/2014 NA NA NA NA NA
2 2/19/2014 NA NA NA NA NA
2 2/20/2014 NA NA NA NA NA
2 2/21/2014 NA NA NA NA NA
2 2/22/2014 NA NA NA NA NA
2 2/23/2014 1 17 22 0 2
2 2/22/2016 NA NA NA NA NA
2 2/23/2016 NA NA NA NA NA
2 2/24/2016 NA NA NA NA NA
2 2/25/2016 NA NA NA NA NA
2 2/26/2016 NA NA NA NA NA
2 2/27/2016 NA NA NA NA NA
2 2/28/2016 1 20 30 1 5
2 3/17/2017 NA 25 32 NA NA
I want to create a new variable sympfl that tracks each day an individual has symptoms
additional info that may be pertinent :
symp - whether a patient has symptoms within the last week
sympTY - whether a patient had these symptoms today or yesterday
sympDays - the number of days the patient had these symptoms within the
past week
Conditions for new sympfl variable:
if symp == 1 and sympTY == 1, then sympfl == 1 starting on the present date going back the number sympDays column holds
if symp == 1 and sympTY == 0, then sympfl == 1 starting 2 days prior to the present date and going back the number the sympDays column holds
The new data set would ideally look like the following:
ID Date symp wt ht sympTY sympDays sympfl
1 1/05/2012 NA NA NA NA NA NA
1 1/06/2012 NA NA NA NA NA NA
1 1/07/2012 NA NA NA NA NA NA
1 1/08/2012 NA NA NA NA NA NA
1 1/09/2012 NA NA NA NA NA 1
1 1/10/2012 NA NA NA NA NA 1
1 1/11/2012 1 23 15 1 3 1
1 1/23/2015 NA 27 19 NA NA NA
2 2/17/2014 NA NA NA NA NA NA
2 2/18/2014 NA NA NA NA NA NA
2 2/19/2014 NA NA NA NA NA NA
2 2/20/2014 NA NA NA NA NA 1
2 2/21/2014 NA NA NA NA NA 1
2 2/22/2014 NA NA NA NA NA NA
2 2/23/2014 1 17 22 0 2 NA
2 2/22/2016 NA NA NA NA NA NA
2 2/23/2016 NA NA NA NA NA NA
2 2/24/2016 NA NA NA NA NA 1
2 2/25/2016 NA NA NA NA NA 1
2 2/26/2016 NA NA NA NA NA 1
2 2/27/2016 NA NA NA NA NA 1
2 2/28/2016 1 20 30 1 5 1
2 3/17/2017 NA 25 32 NA NA NA
I know in order to do this, I can use an if statement, but I'm uncertain how to do this over a number of rows by dates. Any help or direction is greatly appreciated.
Here is a data.table solution which reproduces the expected result for the given sample dataset:
library(data.table)
setDT(DT)[, Date := lubridate::mdy(Date)][
order(ID, -Date), sympfl := {
if (!is.na(first(symp))) {
tmp <- rep(NA_integer_, .N);
replace(tmp, 1 + seq((1 - first(sympTY)) * 3, length.out = first(sympDays)), 1)
}}, by = cumsum(!is.na(symp))][]
ID Date symp wt ht sympTY sympDays sympfl
1: 1 2012-01-05 NA NA NA NA NA NA
2: 1 2012-01-06 NA NA NA NA NA NA
3: 1 2012-01-07 NA NA NA NA NA NA
4: 1 2012-01-08 NA NA NA NA NA NA
5: 1 2012-01-09 NA NA NA NA NA 1
6: 1 2012-01-10 NA NA NA NA NA 1
7: 1 2012-01-11 1 23 15 1 3 1
8: 1 2015-01-23 NA 27 19 NA NA NA
9: 2 2014-02-17 NA NA NA NA NA NA
10: 2 2014-02-18 NA NA NA NA NA NA
11: 2 2014-02-19 NA NA NA NA NA 1
12: 2 2014-02-20 NA NA NA NA NA 1
13: 2 2014-02-21 NA NA NA NA NA NA
14: 2 2014-02-22 NA NA NA NA NA NA
15: 2 2014-02-23 1 17 22 0 2 NA
16: 2 2016-02-22 NA NA NA NA NA NA
17: 2 2016-02-23 NA NA NA NA NA NA
18: 2 2016-02-24 NA NA NA NA NA 1
19: 2 2016-02-25 NA NA NA NA NA 1
20: 2 2016-02-26 NA NA NA NA NA 1
21: 2 2016-02-27 NA NA NA NA NA 1
22: 2 2016-02-28 1 20 30 1 5 1
23: 2 2017-03-17 NA 25 32 NA NA NA
ID Date symp wt ht sympTY sympDays sympfl
Data
library(data.table)
DT <- fread("
ID Date symp wt ht sympTY sympDays
1 1/05/2012 NA NA NA NA NA
1 1/06/2012 NA NA NA NA NA
1 1/07/2012 NA NA NA NA NA
1 1/08/2012 NA NA NA NA NA
1 1/09/2012 NA NA NA NA NA
1 1/10/2012 NA NA NA NA NA
1 1/11/2012 1 23 15 1 3
1 1/23/2015 NA 27 19 NA NA
2 2/17/2014 NA NA NA NA NA
2 2/18/2014 NA NA NA NA NA
2 2/19/2014 NA NA NA NA NA
2 2/20/2014 NA NA NA NA NA
2 2/21/2014 NA NA NA NA NA
2 2/22/2014 NA NA NA NA NA
2 2/23/2014 1 17 22 0 2
2 2/22/2016 NA NA NA NA NA
2 2/23/2016 NA NA NA NA NA
2 2/24/2016 NA NA NA NA NA
2 2/25/2016 NA NA NA NA NA
2 2/26/2016 NA NA NA NA NA
2 2/27/2016 NA NA NA NA NA
2 2/28/2016 1 20 30 1 5
2 3/17/2017 NA 25 32 NA NA ")

Transform a data frame so multiple, overlapping columns form a single scale?

Say I have a data frame as follows (in reality this is multiple data frames bound):
data.frame(
position = c(3,4,7,12,NA,NA,NA,NA,NA,NA,NA,NA),
colb = c(1,3,8,2,NA,NA,NA,NA,NA,NA,NA,NA),
colc = c(4,6,9,5,NA,NA,NA,NA,NA,NA,NA,NA),
position = c(2,7,8,10,11,12,15,16,19,21,24,26),
colb = c(1,3,8),
colc = c(4,6,9)
)
(Sorry, gets flagged if I post the data format myself.)
How can I transform this so I have a unified system of indicating a 'position'? ie one of the two formats below.
A single column scale:
position colb colc colb.1 colc.1
1 NA NA NA NA
2 NA NA 1 4
3 1 4 NA NA
4 3 6 NA NA
5 NA NA NA NA
6 NA NA NA NA
7 8 9 3 6
8 NA NA 8 9
9 NA NA NA NA
10 NA NA 1 4
11 NA NA 3 6
12 2 5 8 9
13 NA NA NA NA
14 NA NA NA NA
15 NA NA 1 4
16 NA NA 3 6
17 NA NA NA NA
18 NA NA NA NA
19 NA NA 8 9
20 NA NA NA NA
21 NA NA 1 4
22 NA NA NA NA
23 NA NA NA NA
24 NA NA 3 6
25 NA NA NA NA
26 NA NA 8 9
Or with separate columns, but 'matching':
position colb colc position.1 colb.1 colc.1
NA NA NA NA NA NA
NA NA NA 2 3 6
3 1 4 NA NA NA
4 3 6 NA NA NA
NA NA NA NA NA NA
NA NA NA NA NA NA
7 8 9 7 1 4
NA NA NA 8 3 6
NA NA NA NA NA NA
NA NA NA 10 1 4
NA NA NA 11 3 6
12 2 5 12 8 9
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA 15 8 9
NA NA NA 16 1 4
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA 19 1 4
NA NA NA NA NA NA
NA NA NA 21 8 9
NA NA NA NA NA NA
NA NA NA NA NA NA
NA NA NA 24 8 9
NA NA NA NA NA NA
NA NA NA 26 8 9
Any help is appreciated. Thanks.
If df contains the dataframe
df <- data.frame(
position = c(3,4,7,12,NA,NA,NA,NA,NA,NA,NA,NA),
colb = c(1,3,8,2,NA,NA,NA,NA,NA,NA,NA,NA),
colc = c(4,6,9,5,NA,NA,NA,NA,NA,NA,NA,NA),
position = c(2,7,8,10,11,12,15,16,19,21,24,26),
colb = c(1,3,8),
colc = c(4,6,9)
)
df1 <- df[,1:3]
df2 <- df[,4:6]
names(df2) <- c("position", "colb", "colc")
df_out <- rbind(df1, df2)
df_out <- df_out[!is.na(df_out$position),]
df_out <- df_out[order(df_out$position),]
df_out

R - List All Combinations With combn (Multiple m Values) [duplicate]

This question already has answers here:
All combinations of all sizes?
(2 answers)
Unordered combinations of all lengths
(3 answers)
Closed 4 years ago.
I would like to build a dataframe that lists all possible combinations of 6 numbers.
I realised that I can use combn(), but with only one value for m. With a bit of playing around I got the desired result by going through step-by-step with the following code -
combi1 <- data.frame(c(1:6))
colnames(combi1) <- 'X1'
combi2 <- data.frame(t(combn(c(1:6), 2)))
combi3 <- data.frame(t(combn(c(1:6), 3)))
combi4 <- data.frame(t(combn(c(1:6), 4)))
combi5 <- data.frame(t(combn(c(1:6), 5)))
combi6 <- data.frame(t(combn(c(1:6), 6)))
Combi <- rbind.fill(combi1, combi2, combi3, combi4, combi5, combi6)
I had to transpose each of the DFs to get them in the right shape.
My problem is that this seems to be quite an in-efficient method. Maybe a bit simplistic. I thought there must surely be some quicker way to code this, but haven't found any solution online that gives me what I'd like.
Possibly build it into a function or a loop somehow? I'm fairly new to R though and haven't had a great deal of practice writing functions.
Is it what you want ?
combis <- vector("list", 6)
combi1 <- data.frame(c(1:6))
colnames(combi1) <- 'X1'
combis[[1]] <- combi1
combis[2:6] <- lapply(2:6, function(n) data.frame(t(combn(c(1:6), n))))
do.call(plyr::rbind.fill, combis)
Result:
X1 X2 X3 X4 X5 X6
1 1 NA NA NA NA NA
2 2 NA NA NA NA NA
3 3 NA NA NA NA NA
4 4 NA NA NA NA NA
5 5 NA NA NA NA NA
6 6 NA NA NA NA NA
7 1 2 NA NA NA NA
8 1 3 NA NA NA NA
9 1 4 NA NA NA NA
10 1 5 NA NA NA NA
11 1 6 NA NA NA NA
12 2 3 NA NA NA NA
13 2 4 NA NA NA NA
14 2 5 NA NA NA NA
15 2 6 NA NA NA NA
16 3 4 NA NA NA NA
17 3 5 NA NA NA NA
18 3 6 NA NA NA NA
19 4 5 NA NA NA NA
20 4 6 NA NA NA NA
21 5 6 NA NA NA NA
22 1 2 3 NA NA NA
23 1 2 4 NA NA NA
24 1 2 5 NA NA NA
25 1 2 6 NA NA NA
26 1 3 4 NA NA NA
27 1 3 5 NA NA NA
28 1 3 6 NA NA NA
29 1 4 5 NA NA NA
30 1 4 6 NA NA NA
31 1 5 6 NA NA NA
32 2 3 4 NA NA NA
33 2 3 5 NA NA NA
34 2 3 6 NA NA NA
35 2 4 5 NA NA NA
36 2 4 6 NA NA NA
37 2 5 6 NA NA NA
38 3 4 5 NA NA NA
39 3 4 6 NA NA NA
40 3 5 6 NA NA NA
41 4 5 6 NA NA NA
42 1 2 3 4 NA NA
43 1 2 3 5 NA NA
44 1 2 3 6 NA NA
45 1 2 4 5 NA NA
46 1 2 4 6 NA NA
47 1 2 5 6 NA NA
48 1 3 4 5 NA NA
49 1 3 4 6 NA NA
50 1 3 5 6 NA NA
51 1 4 5 6 NA NA
52 2 3 4 5 NA NA
53 2 3 4 6 NA NA
54 2 3 5 6 NA NA
55 2 4 5 6 NA NA
56 3 4 5 6 NA NA
57 1 2 3 4 5 NA
58 1 2 3 4 6 NA
59 1 2 3 5 6 NA
60 1 2 4 5 6 NA
61 1 3 4 5 6 NA
62 2 3 4 5 6 NA
63 1 2 3 4 5 6

Replace values occuring once in raster by NA

I have vector of values(generated from raster - Raster package - by function clump in R):
values(rc)
1 NA NA NA 2 NA 2 2 NA NA NA NA NA NA NA 2 NA 2 2 NA 2 2 NA NA NA
NA NA NA NA 2 NA NA NA NA NA 3 NA 4 NA 2 NA 2 NA 5 NA NA 3 NA NA 4
NA NA 2 NA NA NA NA NA NA NA NA 4 NA NA NA NA NA NA 6 NA 7 NA 4 NA NA
NA 8 8 NA 6 6 NA NA NA NA 4 NA NA NA NA NA NA NA NA 4 4 4 NA NA 9
NA NA NA NA 10 NA NA NA NA 4 NA 9 9 NA NA NA NA 10 NA NA NA 4 NA NA NA
9 NA NA NA NA NA NA NA NA NA 11 NA NA NA 12 NA NA NA NA
and I would like to find every value which occurs only once(so 1,5,11,10) and replace it by NA. What I would like to obtain:
values(replaced_rc)
NA NA NA NA 2 NA 2 2 NA NA NA NA NA NA NA 2 NA 2 2 NA 2 2 NA NA NA
NA NA NA NA 2 NA NA NA NA NA 3 NA 4 NA 2 NA 2 NA NA NA NA 3 NA NA 4
NA NA 2 NA NA NA NA NA NA NA NA 4 NA NA NA NA NA NA 6 NA NA NA 4 NA NA
NA 8 8 NA 6 6 NA NA NA NA 4 NA NA NA NA NA NA NA NA 4 4 4 NA NA 9
NA NA NA NA 10 NA NA NA NA 4 NA 9 9 NA NA NA NA 10 NA NA NA 4 NA NA NA
9 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
The problem is that I can easily identify raster patches by function clump. And I would like to exclude patches containing only pixel, similarly like function "sieve" in ENVI or ERDAS. Any help? Thanks a lot in advance.
Exemple from R:
library("raster")
r <- raster(ncols=12, nrows=12)
set.seed(0)
r[] <- round(runif(ncell(r))*0.7 )
plot(r)
rc <- clump(r)
replaced_rc<- ???
Using duplicated:
values(rc)[!duplicated(values(rc)) & !duplicated(values(rc),fromLast=T)] <- NA

Resources