How to Add Multiple Columns to a Tibble

How to add multiple columns to a tibble?

What you are seeing in tibble::add_column(columnsToAdd = NA) is the quasi-something evaluation that dplyr and tidyr introduced. If you check the definition:

> args(add_column)
function (.data, ..., .before = NULL, .after = NULL)

you'll see that it doesn't expect a certain variable. It literally expects the actual variable name, without quotation.

An entirely different approach is to create a matrix (or data.frame, whatever tickles your fancy), and smack it onto the side of someTibble:

extra <- matrix(NA_real_, nrow=nrow(someTibble), ncol=length(columnsToAdd), dimnames=list(NULL, columnsToAdd))
dplyr::bind_cols(someTibble, as.data.frame(extra))

Dplyr: add multiple columns with mutate/across from character vector

The !! works for a single element

for(nm in add_cols) test <- test %>% 
mutate(!! nm := NA)

-output

> test
a col_1 col_2
1 1 NA NA
2 2 NA NA
3 3 NA NA

Or another option is

test %>% 
bind_cols(setNames(rep(list(NA), length(add_cols)), add_cols))
a col_1 col_2
1 1 NA NA
2 2 NA NA
3 3 NA NA

In base R, this is easier

test[add_cols] <- NA

Which can be used in a pipe

test %>%
`[<-`(., add_cols, value = NA)
a col_1 col_2
1 1 NA NA
2 2 NA NA
3 3 NA NA

across works only if the columns are already present i.e. it is suggesting to loop across the columns present in the data and do some modification/create new columns with .names modification


We could make use add_column from tibble

library(tibble)
library(janitor)
add_column(test, !!! add_cols) %>%
clean_names %>%
mutate(across(all_of(add_cols), ~ NA))
a col_1 col_2
1 1 NA NA
2 2 NA NA
3 3 NA NA

Create multiple new columns in tibble in R based on value of previous row giving prefix to all

You could do this this way

df_new <- bind_cols(
df,
df %>% mutate_at(.vars = vars("a","b","c"), function(x) lag(x))
)

Names are a bit nasty but you can rename them check here. Or see @Bas comment to get the names with a suffix.

# A tibble: 10 x 6
a b c a1 b1 c1
<int> <int> <int> <int> <int> <int>
1 1 21 31 NA NA NA
2 2 22 32 1 21 31
3 3 23 33 2 22 32
4 4 24 34 3 23 33
5 5 25 35 4 24 34
6 6 26 36 5 25 35
7 7 27 37 6 26 36
8 8 28 38 7 27 37
9 9 29 39 8 28 38
10 10 30 40 9 29 39

If you have dplyr 1.0 you can use the new accross() function.

See some expamples from the docs, instead of mean you want lag

df %>% mutate_if(is.numeric, mean, na.rm = TRUE)
# ->
df %>% mutate(across(is.numeric, mean, na.rm = TRUE))

df %>% mutate_at(vars(x, starts_with("y")), mean, na.rm = TRUE)
# ->
df %>% mutate(across(c(x, starts_with("y")), mean, na.rm = TRUE))

df %>% mutate_all(mean, na.rm = TRUE)
# ->
df %>% mutate(across(everything(), mean, na.rm = TRUE))

adding multiple columns dynamically in tidyverse

Making use of across and where you could do:

library(dplyr)
library(lubridate)

mutate(smpl, across(where(is.POSIXct), lubridate::wday,
label=TRUE, abbr=FALSE, .names = "{.col}_day"))
#> # A tibble: 6 x 10
#> mealTime weight_measure_time height_measure_time
#> <dttm> <dttm> <dttm>
#> 1 2018-11-17 22:00:00 2018-11-14 20:06:40 2018-11-13 10:53:54
#> 2 2020-01-12 18:00:00 2020-01-12 07:00:00 2018-11-27 16:44:03
#> 3 2020-11-01 18:00:00 2020-07-14 07:00:00 2018-11-27 16:44:03
#> 4 2018-12-27 09:00:00 2018-12-27 07:46:02 2018-11-16 17:06:28
#> 5 2019-02-10 18:00:00 2019-01-02 08:13:43 2018-11-16 11:09:07
#> 6 2018-12-08 22:00:00 2018-12-08 00:00:45 2018-11-21 12:10:28
#> # … with 7 more variables: hba1c_measure_time <dttm>, bpMeasureTime <dttm>,
#> # mealTime_day <dbl>, weight_measure_time_day <dbl>,
#> # height_measure_time_day <dbl>, hba1c_measure_time_day <dbl>,
#> # bpMeasureTime_day <dbl>

Convert a tibble column that is a multi-column-tibble to just a tibble with multiple columns

You could just pull it out and bind it on:

out %>% bind_cols(pull(., value)) %>% select(-value)
# A tibble: 100 x 3
z PC1 PC2
<dbl> <dbl> <dbl>
1 1 0.732 0.349
2 1 -0.512 1.02
3 1 2.44 1.56
4 1 1.68 -1.70
5 1 1.31 1.20
6 1 -1.16 -1.84
7 1 0.350 -0.0767
8 1 -0.611 -1.02
9 1 -0.901 -0.638
10 1 -0.709 0.0443
# ... with 90 more rows

Adding multiple columns at certain positions in dataframe in R

With a slight tweak your code works although there's probably better ways to do this:

for (i in 1:3) {
df <- df %>%
add_column(!!paste0("AB", i, collapse = "") := "X" , .before = paste0("B", i, collapse = ""))
}

Add multiple columns with the same group and sum

If I have understood you well, this will solve your problem:

narc_auth_total <- 
narc_auth %>%
group_by(Full.Name) %>%
summarise(
`2019_words` = sum(`2019`),
`2020_words` = sum(`2020`)
) %>%
left_join(totaltweetsyear, ., by = "Full.Name")

Adding multiple columns in between columns in a data frame using a For Loop

You do not need to loop to do this:

as.data.frame(cbind(df, matrix(0, nrow = nrow(df), ncol = 53)))

Store.No Task Third Fourth 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
1 1 70 4 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 2 50 5 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 3 20 6 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  1. matrix will create a matrix with 53 columns and 3 rows filled with 0

  2. cbind will add this matrix to the end of your data

  3. as.data.frame will convert it to a dataframe

Update

To insert these zero columns positionally you can subset your df into two parts: df[, 1:2] are the first and second columns, while df[,3:ncol(df)] are the third to end of your dataframe.

as.data.frame(cbind(df[,1:2], matrix(0, nrow = nrow(df), ncol = 53), df[,3:ncol(df)))

Store.No Task 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
1 1 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 2 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 3 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 Third Fourth
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 7
2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 8
3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 9

add_column

Alternatively you can use the add_column function from the tibble package as you were in your post using the .after argument to insert after the second column:

library(tibble)

tibble::add_column(df, as.data.frame(matrix(0, nrow = nrow(df), ncol = 53)), .after = 2)

Note: this function will fix the column names to add a "V" before any column name that starts with a number. So 1 will become V1.


Data

df <- data.frame(Store.No = 1:3,
Task = c(70, 50, 20),
Third = 4:6,
Fourth = 7:9)

dplyr::mutate to add multiple values

Yet another variant, although I think we're all splitting hairs here.

> dd <- data.frame(x=c(3,4),n=c(10,11))
> get_binCI <- function(x,n) {
+ as_data_frame(setNames(as.list(binom.test(x,n)$conf.int),c("lwr","upr")))
+ }
>
> dd %>%
+ group_by(x,n) %>%
+ do(get_binCI(.$x,.$n))
Source: local data frame [2 x 4]
Groups: x, n

x n lwr upr
1 3 10 0.06673951 0.6524529
2 4 11 0.10926344 0.6920953

Personally, if we're just going by readability, I find this preferable:

foo  <- function(x,n){
bi <- binom.test(x,n)$conf.int
data_frame(lwr = bi[1],
upr = bi[2])
}

dd %>%
group_by(x,n) %>%
do(foo(.$x,.$n))

...but now we're really splitting hairs.

Better way to add tibble column to df in iterative fashion

tibbles square bracket subsetting doesn't drop by default, so it always stays a tibble.

Just change

df$output = df_tibble[, i]

to

df$output = df_tibble[, i, drop = TRUE]


Related Topics



Leave a reply



Submit