pulling data from data frame in R - r

I'm trying to create a vector using data from my data frame which contains all of the numeric values in the data frame.
Basically, I want a vector that has (2,2,5,2,2,3,2,3,2,2,2,2,2).
two three four five six seven
2 NA NA NA NA NA
2 NA NA NA NA NA
NA NA NA 5 NA NA
2 NA NA NA NA NA
2 NA NA NA NA NA
NA 3 NA NA NA NA
2 NA NA NA NA NA
NA 3 NA NA NA NA
2 NA NA NA NA NA
2 NA NA NA NA NA
2 NA NA NA NA NA
2 NA NA NA NA NA
2 NA NA NA NA NA

Just subset the dataframe for non-NA values with !is.na(df):
df <- data.frame(two = c(2, 2, NA),
three = c(NA, NA, NA),
four = c(NA, 3, NA))
df
# two three four
# 1 2 NA NA
# 2 2 NA 3
# 3 NA NA NA
is.na(df)
# two three four
# [1,] FALSE TRUE TRUE
# [2,] FALSE TRUE FALSE
# [3,] TRUE TRUE TRUE
df[!is.na(df)]
# [1] 2 2 3

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"))

Create a data.frame with all transition counts

Assume a data.frame:
df <- data.frame(name = c("a","b","c","d","e"),rank = c(1,1,4,3,2))
name rank
a 1
b 1
c 4
d 3
e 2
Based on the above data.frame, I want to create a new one that holds the count of transitions from one rank to another. So the output would be something like this:
name 1to1 1to2 1to3 1to4 2to1 2to2 2to3 2to4 3to1 3to2 3to3 3to4 4to1 4to2 4to3 4to4
1 b 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2 c NA NA NA 1 NA NA NA NA NA NA NA NA NA NA NA NA
3 d NA NA NA NA NA NA NA NA NA NA NA NA NA NA 1 NA
4 e NA NA NA NA NA NA NA NA NA 1 NA NA NA NA NA NA
One way to do this would be to run a for loop and then using ifs but I am pretty sure there should be a more efficient way of doing this.
For example, if item d has a rank of 3 and item c is ranked as 4 then the code should increase the count of the 4to3 column under d's row (as per example above). Please let me know if this is unclear and I appreciate all the help.
P.S. colnames are not that important.
You could use Map to create sequences for extracting the transitions and collapse them into the desired form using paste.
tmp <- sapply(Map(seq, 1:(nrow(df1)-1), 2:nrow(df1)), function(i) df1$rank[i])
v <- apply(tmp, 2, function(x) paste(x, collapse="to"))
Then create a grid with all permutations
to <- apply(expand.grid(1:4, 1:4), 1, function(x) paste(x, collapse="to"))
and compare them with the actual transitions to get the resulting binary structure; create a data frame out of it.
res <- data.frame(name=df1$name[-1], t(sapply(v, function(i) setNames(+(i == to), to))))
Afterwards, you may convert the zeroes to NA using
res[res == 0] <- NA
Result
res
# name X1to1 X2to1 X3to1 X4to1 X1to2 X2to2 X3to2 X4to2 X1to3 X2to3 X3to3 X4to3 X1to4 X2to4 X3to4 X4to4
# 1to1 b 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# 1to4 c NA NA NA NA NA NA NA NA NA NA NA NA 1 NA NA NA
# 4to3 d NA NA NA NA NA NA NA NA NA NA NA 1 NA NA NA NA
# 3to2 e NA NA NA NA NA NA 1 NA NA NA NA NA NA NA NA NA
Data
df1 <- structure(list(name = structure(1:5, .Label = c("a", "b", "c",
"d", "e"), class = "factor"), rank = c(1, 1, 4, 3, 2)), class = "data.frame", row.names = c(NA,
-5L))

Set consequent non na values to NA

Set every non-NA value that has a non-NA value to "his left" to NA.
Data
a <- c(3,2,3,NA,NA,1,NA,NA,2,1,4,NA)
[1] 3 2 3 NA NA 1 NA NA 2 1 4 NA
Desired Output
[1] 3 NA NA NA NA 1 NA NA 2 NA NA NA
My working but ugly solution:
IND <- !(is.na(a)) & data.table::rleidv(!(is.na(a))) %>% duplicated
a[IND]<- NA
a
There's gotta be a better solution ...
Alternatively,
a[-1][diff(!is.na(a)) == 0] <- NA; a
# [1] 3 NA NA NA NA 1 NA NA 2 NA NA NA
OK for brevity...
a[!is.na(dplyr::lag(a))]<-NA
a
[1] 3 NA NA NA NA 1 NA NA 2 NA NA NA
You can do a simple ifelse statement where you add your vector with a lagged vector a. If the result is NA then the value should remain the same. Else, NA, i.e.
ifelse(is.na(a + dplyr::lag(a)), a, NA)
#[1] 3 NA NA NA NA 1 NA NA 2 NA NA NA

Subsets defined by k-way combinations of factors in R

I would like to apply a function (will be a custom function, but for simplicity I will say it is mean) to subgroups defined by combinations of factors. I have 20 factors, but I would like to consider, say, subgroups defined by all combinations of 1,2,3,...,k of the factors.
Here is an example for k=3
N = 100
test_data <- data.frame( factorA = factor(sample(1:4, replace = TRUE, size = N)), factorB = factor(sample(1:2, replace = TRUE, size = N)), factorC = factor(sample(1:2, replace = TRUE, size = N)), var = rnorm(n = N))
#1-way subsets
mean(test_data$var[test_data$factorA == "1"])
mean(test_data$var[test_data$factorA == "2"])
mean(test_data$var[test_data$factorA == "3"])
mean(test_data$var[test_data$factorA == "4"])
mean(test_data$var[test_data$factorB == "1"])
#and so forth...
#2-way subsets
mean(test_data$var[test_data$factorA == "1" & test_data$factorB == "1" ])
mean(test_data$var[test_data$factorA == "1" & test_data$factorB == "2" ])
mean(test_data$var[test_data$factorA == "1" & test_data$factorC == "1" ])
#and so forth...
#3-way subsets
mean(test_data$var[test_data$factorA == "1" & test_data$factorB == "1" & test_data$factorC == "1" ])
mean(test_data$var[test_data$factorA == "1" & test_data$factorB == "1" & test_data$factorC == "2" ])
#and so forth...
For each combinations of k factors, compute the mean of var for all combinations of levels for these k factors. It would be best if the output is then labeled the given combination of factors/levels that defines the subset.
It seems that expand.grid and/or combn should be useful, but not sure how to use them in this situation.
To calculate the mean of var for all combinations of all three factors you can use the data.table by argument:
library(data.table)
N = 100
test_data <- data.frame(factorA = factor(sample(1:4, replace = TRUE, size = N)),
factorB = factor(sample(1:2, replace = TRUE, size = N)),
factorC = factor(sample(1:2, replace = TRUE, size = N)), var = rnorm(n = N))
setDT(test_data)
test_data[, .(mean_var = mean(var, na.rm = TRUE)),
by = .(factorA, factorB, factorC)]
Which gives this output:
factorA factorB factorC mean_var
1: 1 1 1 -0.304218613
2: 1 1 2 -0.122405096
3: 1 2 1 0.532219871
4: 1 2 2 -0.679400706
5: 2 1 1 0.006901209
6: 2 1 2 0.605850466
7: 2 2 1 -0.083305497
8: 2 2 2 -0.408660971
9: 3 1 1 -0.362234218
10: 3 1 2 -0.368472511
11: 3 2 1 0.243274183
12: 3 2 2 0.119927615
13: 4 1 1 -0.517337915
14: 4 1 2 -0.790908511
15: 4 2 1 -0.077665828
16: 4 2 2 -0.295695277
Updated with example data containing 20 factor columns (with two to four levels each). All possible combinations of three factors (i.e. columns) are generated (6480) and for each combination the mean_var for each unique combination of factor levels is calculated:
library(data.table)
# Generate example data
N = 100
dt <- dcast(rbindlist(lapply(seq(1:20), function(x) {
dt_tmp <- data.table(id = 1:N, factor = paste0("factor", LETTERS[x]),
value = sample(1:sample(2:4, 1), replace = TRUE, size = N))
})), id~factor)[, ":="(var = rnorm(n = N), id = NULL)]
# Generate all combinations of three out of the 20 factors (20*19*18 = 6840)
factors <- colnames(dt[, 1:20])
tests <- CJ(k1 = factors, k2 = factors, k3 = factors)[k1 != k2 & k1 != k3 & k2 != k3]
# Iterate over every row of tests and calculate mean_var for each unique
# combination of the three factors (this takes time - output ~ 170000 rows)
dt_out <- rbindlist(lapply(seq(1:nrow(tests)), function(x) {
dt[, .(mean_var = mean(var, na.rm = TRUE)),
by = c(tests[x, k1], tests[x, k2], tests[x, k3])]
}), use.names = TRUE, fill = TRUE)
The output looks like this:
> head(out_dt, 30)
factorA factorB factorC mean_var factorD factorE factorF factorG factorH factorI factorJ factorK factorL factorM factorN factorO factorP factorQ factorR factorS factorT
1: 1 2 3 -0.595391823 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2: 2 1 1 -0.049915238 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
3: 2 2 4 0.087206182 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
4: 2 1 2 0.010622079 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
5: 1 2 1 0.277414685 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
6: 1 1 3 0.366482963 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
7: 2 2 3 0.017438655 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
8: 2 2 1 -1.116071505 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
9: 2 1 4 1.371340706 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
10: 2 2 2 0.045354904 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
11: 1 2 2 0.644926008 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
12: 1 2 4 -0.121767568 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
13: 1 1 2 0.261070274 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
14: 2 1 3 -0.506061865 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
15: 1 1 4 -0.075228598 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
16: 1 1 1 0.333514316 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
17: 1 2 NA -0.185980008 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
18: 2 1 NA -0.113793548 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
19: 2 2 NA 0.015100176 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
20: 1 2 NA 0.484182038 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
21: 1 1 NA -0.123811140 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
22: 1 1 NA 0.543852715 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
23: 2 2 NA -0.267626769 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
24: 2 1 NA 0.133316773 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
25: 1 2 NA 0.538964320 NA 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
26: 2 1 NA 0.006298113 NA 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
27: 2 2 NA 0.010152043 NA 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
28: 2 1 NA 0.011377912 NA 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
29: 1 1 NA 0.504610954 NA 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
30: 2 2 NA -0.311834384 NA 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
factorA factorB factorC mean_var factorD factorE factorF factorG factorH factorI factorJ factorK factorL factorM factorN factorO factorP factorQ factorR factorS factorT

Fill matrix with column values in R using colnames and rownames

I have a very large dataset, so I want to avoid loops.
I have three columns of data:
col1 = time presented as 10000, 10001, 10002, 10100, 10101, 10102,
10200, 10201, 10202, 10300, ... (total 18000 times)
col2 = id number 1 2 3 4 ... (total 500 ids)
col3 = reading associated with particular id at particular time. 0.1
0.5 0.6 0.7... Say this is called Data3
10000 1 0.1
10001 1 0.5
10002 1 0.6
10100 1 0.7
10200 1 0.6 (NOTE - some random entries missing)
I want to present this as a matrix (called DataMatrix), but there is missing data, so a simple reshape will not do. I want to have the missing data as NA entries.
DataMatrix is currently an NA matrix of 500 columns and 18000 rows, where the row names and column names are the times and ids respectively.
1 2 3 4 ....
10000 NA NA NA NA ....
10001 NA NA NA NA ....
Is there a way I can get R to go through each row of Data3, completing DataMatrix with the reading Data3[,3] by placing it in the row and column of the matrix whose names relate to the Data3[,1] and Data3[,2]. But without loops.
Thanks to all you smart people out there.
If I understood you correctly:
Data3 <- data.frame(col1=10000:10499,
col2=1:500,
col3=round(runif(500),1))
library(reshape2)
DataMatrix <- dcast(Data3, col1~col2, value.var="col3")
DataMatrix[1:5, 1:5]
# col1 1 2 3 4
# 1 10000 0.4 NA NA NA
# 2 10001 NA 0.6 NA NA
# 3 10002 NA NA 0.9 NA
# 4 10003 NA NA NA 0.5
# 5 10004 NA NA NA NA
Here is a solution with possible id values in 1:10 and times values in 1:20. First, create data:
mx <- matrix(c(sample(1:20, 5), sample(1:10, 5), sample(1:50, 5)), ncol=3, dimnames=list(NULL, c("time", "id", "reading")))
times <- 1:20
ids <- 1:10
mx
# time id reading
# [1,] 4 3 25
# [2,] 5 4 9
# [3,] 9 7 45
# [4,] 18 1 40
# [5,] 11 8 28
Now, use outer to pass every possible combination of time/id to a look up function that returns the corresponding reading value:
outer(times, ids,
function(x, y) {
mapply(function(x.sub, y.sub) {
val <- mx[mx[, 1] == x.sub & mx[, 2] == y.sub, 3]
if(length(val) == 0L) NA_integer_ else val
},
x, y)
} )
This produces the (hopefully) desired answer:
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] NA NA NA NA NA NA NA NA NA NA
# [2,] NA NA NA NA NA NA NA NA NA NA
# [3,] NA NA NA NA NA NA NA NA NA NA
# [4,] NA NA 25 NA NA NA NA NA NA NA
# [5,] NA NA NA 9 NA NA NA NA NA NA
# [6,] NA NA NA NA NA NA NA NA NA NA
# [7,] NA NA NA NA NA NA NA NA NA NA
# [8,] NA NA NA NA NA NA NA NA NA NA
# [9,] NA NA NA NA NA NA 45 NA NA NA
# [10,] NA NA NA NA NA NA NA NA NA NA
# [11,] NA NA NA NA NA NA NA 28 NA NA
# [12,] NA NA NA NA NA NA NA NA NA NA
# [13,] NA NA NA NA NA NA NA NA NA NA
# [14,] NA NA NA NA NA NA NA NA NA NA
# [15,] NA NA NA NA NA NA NA NA NA NA
# [16,] NA NA NA NA NA NA NA NA NA NA
# [17,] NA NA NA NA NA NA NA NA NA NA
# [18,] 40 NA NA NA NA NA NA NA NA NA
# [19,] NA NA NA NA NA NA NA NA NA NA
# [20,] NA NA NA NA NA NA NA NA NA NA

Resources