Reputation: 41
Beginner here: I'm trying to apply the prop.test function in r to each row of a dataframe. If I have a large table, how can I apply the function row-wise without referencing each element? I tried the broom::tidy function but this provides only the proportion and I need the 95% confidence intervals.
> a<-data.frame(x=c(1,2,3,4),y=c(5,6,7,8))
> z=rowSums(a)
> b<-cbind(a,z)
> b
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
# inefficient code:
prop.test(b[1,1],b[1,3])
prop.test(b[2,1],b[2,3])
prop.test(b[3,1],b[3,3])
prop.test(b[4,1],b[4,3])
# doesn't provide 95% confidence intervals
broom::tidy(prop.test(b$x, b$z))
Upvotes: 4
Views: 2257
Reputation: 887691
We may need rowwise
operation instead of applying prop.test
on the entire columns
library(dplyr)
library(tidyr)
library(broom)
b %>%
rowwise %>%
summarise(out = list(prop.test(x, z) %>%
tidy)) %>%
ungroup %>%
unnest(cols = c(out))
-output
# A tibble: 4 x 8
estimate statistic p.value parameter conf.low conf.high method alternative
<dbl> <dbl> <dbl> <int> <dbl> <dbl> <chr> <chr>
1 0.167 1.5 0.221 1 0.00876 0.635 1-sample proportions test with continuity correction two.sided
2 0.25 1.12 0.289 1 0.0445 0.644 1-sample proportions test with continuity correction two.sided
3 0.3 0.9 0.343 1 0.0809 0.646 1-sample proportions test with continuity correction two.sided
4 0.333 0.75 0.386 1 0.113 0.646 1-sample proportions test with continuity correction two.sided
Or in base R
, it would be Map
do.call(rbind, Map(\(x, y) tidy(prop.test(x, y)), b$x, b$z))
-output
# A tibble: 4 x 8
estimate statistic p.value parameter conf.low conf.high method alternative
<dbl> <dbl> <dbl> <int> <dbl> <dbl> <chr> <chr>
1 0.167 1.5 0.221 1 0.00876 0.635 1-sample proportions test with continuity correction two.sided
2 0.25 1.12 0.289 1 0.0445 0.644 1-sample proportions test with continuity correction two.sided
3 0.3 0.9 0.343 1 0.0809 0.646 1-sample proportions test with continuity correction two.sided
4 0.333 0.75 0.386 1 0.113 0.646 1-sample proportions test with continuity correction two.sided
Upvotes: 2
Reputation: 96976
You could use apply
to apply a function to each row of a data frame:
apply(b, 1, function(df) prop.test(df[1], df[3]))
This returns a list:
l <- apply(b, 1, function(df) prop.test(df[1], df[3]))
typeof(l)
[1] "list"
So you could access these by list indices, e.g. [[1]]
, [[2]]
, etc. You could also use unlist(l)
to unwrap the list, but this may not give results that are as easy to access.
You could also apply by column label:
apply(b, 1, function(df) prop.test(df['x'], df['z']))
Upvotes: 1
Reputation: 1527
Or with a simple function:
myFun <- function(x) {
for (i in c(1:nrow(x))) {
print(prop.test(b[i,1],b[i,3]))
}
}
myFun(b)
Upvotes: 1