how to apply functions on data frame in r - r

How can i apply the following function rt on each and every value l in df.
x and y have the following values.
x<-9
y<-1
rt<-function(x,y,l) min(x,max(0,l-y))
df
a b c
5 6 7
1 4 1
2 4 3

Probably simplest if you'd like to stick with dataframes is to use apply with the MARGIN parameter set to c(1,2), which makes it apply the function by both rows and columns (i.e., to every cell).
x <- 9
y <- 1
rt <- function(x, y, l) min(x, max(0, l-y))
df <- data.frame(a = c(5, 1, 2),
b = c(6, 4, 4),
c = c(7, 1, 3))
rt_df <- as.data.frame(apply(df, c(1,2), rt, x = x, y = y))

Related

Multiplication in FUN argument

I have this dataframe
x <- data.frame(
matrix(
c(letters[1:3], c("x", "x", "y") ,
sample(c(rep(1,100),0), size = 1),
sample(c(rep(1,100),0), size = 1),
sample(c(rep(1,100),0), size = 1)), ncol = 3)
)
I would like to do multiplication by group X and Y.
My suggestion
agg <- aggregate(x$X3,
by = list(x$X2),
FUN = *)
I would like to use something like sum, mean byt to multiply
+ is to sum as * is to prod (for product).
Your sample data follows the anti-pattern of data.frame(matrix()). A matrix can only have one data type. You mix character and numeric data in the matrix, and the matrix makes it all character class, and you can't do math on characters. Here's proper sample data and a demonstration the solution works. Also note that using by = X["X2"] instead of by = list(x$X2) gives a nicer column name in the result.
(x <- data.frame(
X1 = letters[1:3],
X2 = c("x", "x", "y") ,
X3 = 2:4
))
# X1 X2 X3
# 1 a x 2
# 2 b x 3
# 3 c y 4
aggregate(x$X3, by = x["X2"], FUN = prod)
# X2 x
# 1 x 6
# 2 y 4
Either use prod or use Reduce with *. Also convert X3 to numeric and and use single brackets as shown to preserve the names. Alternately use the aggregate formula method, shown only for prod but applies to Reduce as well.
xx <- transform(x, X3 = as.numeric(X3))
aggregate(xx["X3"], by = xx["X2"], FUN = prod)
aggregate(xx["X3"], by = xx["X2"], FUN = Reduce, f = `*`) # same
aggregate(X3 ~ X2, xx, FUN = prod)
A better example might be to use mtcars that comes with R:
aggregate(mtcars["mpg"], by = mtcars["cyl"], FUN = prod)
aggregate(mtcars["mpg"], by = mtcars["cyl"], FUN = Reduce, f = `*`) # same
aggregate(mpg ~ cyl, mtcars, FUN = prod)

Providing the correct match for a list in a list of lists in R

I have a list of lists in R:
a <- list(x=0, y=c(1,2,3), z=4)
b <- list(x=1, y=c(1,2,3), z=44)
c <- list(x=2, y=c(1,2,3), z=444)
L <- list(a,b,c)
For a given list, say
l <- list(x=0, y=c(1,2,3), z=4)
I know want to find the correct index of L where we find the corresponding list that equals l.
Of course, I can use a loop, but since Lis very large, I need a faster solution.
(And is a list even the right choice here?)
We can use stack with identical from base R
which(sapply(L, function(x) identical(stack(l), stack(x))))
#[1] 1
Or more compactly
which(sapply(L, identical, l))
#[1] 1
Using mapply to compare each element one by one with l. If you unlist it, all should be TRUE. Using which around an sapply finally gives the number of the matching element.
f <- function(x) all(unlist(mapply(`==`, x, l)))
which(sapply(L, f))
# [1] 1
Data:
L <- list(list(x = 0, y = c(1, 2, 3), z = 4), list(x = 1, y = c(1,
2, 3), z = 44), list(x = 2, y = c(1, 2, 3), z = 444))
l <- list(x = 0, y = c(1, 2, 3), z = 4)
Perhaps you can try mapply like below
> which(mapply(identical, L, list(l)))
[1] 1

Unpack a list by duplicating elements longer than 1

I have the following list that I wish to unpack (aka expand) using only base R.
For example, I want to turn this:
b <- list(a = c(1, 2), b = 1, d = c(5, 7))
into the equivalent of:
list(a = 1, a = 2, b = 1, d = 5, d = 7)
I have this function that works if only one named element has length > 1 but not if there are multiple elements:
expand_list <- function(listx){
long_elements <- as.numeric(which(lapply(listx, length) > 1))
short_elements <- as.numeric(which(lapply(listx, length) == 1))
res <- lapply(long_elements, function(x){
as.list(setNames(listx[[x]], rep(names(listx)[x], length(listx[[x]]))))
})
expanded_elements <- res[[1]]
c(listx[short_elements], expanded_elements)
}
expand_list(b)
You can use stack followed by setNames to achieve that
y <- list(a = c(1, 2), b = 1, c = 2, d = c(5, 7))
x <- stack(y)
as.list(setNames(x$values, x$ind))

Creating a data frame from nrow results of different vectors/data frames

I have some vectors in different data.frames. I want to count the number of observations of each vectors and make a list out of it. The first column should be the data frame names and the second columns should be the number of observations in each data frame. A minimal example could be,
x <- c(1, 3, 4, 5, 6)
x1 <- data.frame(x)
y <- c(3, 9)
y1 <- data.frame(y)
z <- c(23, 43, 23, 12, 1, 3, 7,8,9)
z1 <- data.frame(z)
a <- nrow(x1)
b <- nrow(y1)
c <- nrow(z1)
d <- c(a, b, c)
e <- data.frame(d)
e
The output e looks like this,
> e
d
1 5
2 2
3 9
However, I want that in this way,
> e
df.name nobs
1 x1 5
2 y1 2
3 z1 9
Any help would be greately appreciated.
Is this what you want?
x <- c(1, 3, 4, 5, 6)
x1 <- data.frame(x)
y <- c(3, 9)
y1 <- data.frame(y)
z <- c(23, 43, 23, 12, 1, 3, 7,8,9)
z1 <- data.frame(z)
library(purrr)
targlist <- list(x1,y1,z1)
data.frame(
names=unlist(map(targlist,names)),
nobs=unlist(map(targlist,nrow))
)
If there's more than one col names is going to misbehave. Maybe you want names=paste0("x",1:length(targlist)) instead. But this was fun for your example.
We can do this with base R
stack(lapply(mget(c("x1", "y1", "z1")), nrow))[2:1]

Create a list from matrix in R

I have two lists v and w and I would like to create again a list z from matrix M . How can I do this in R?
v = list(a = c(1, 5), b = 2, c= 3)
w = list( a= c(2, 10), b = 4, c = 6)
M = as.matrix(unlist( v) * unlist(w))
> M
[,1]
a1 2
a2 50
b 8
c 18
z = list(a = c(2, 50), b = 8, c = 18)
Do it like this:
mapply(`*`, v, w)
Maybe you want z <- lapply(1:length(v), function(i) v[[i]]*w[[i]])? Add names(z) <- names(v) to keep the names.

Resources