How to Append Rows to an R Data Frame

How to add a row to a data frame in R?

Like @Khashaa and @Richard Scriven point out in comments, you have to set consistent column names for all the data frames you want to append.

Hence, you need to explicitly declare the columns names for the second data frame, de, then use rbind(). You only set column names for the first data frame, df:

df<-data.frame("hi","bye")
names(df)<-c("hello","goodbye")

de<-data.frame("hola","ciao")
names(de)<-c("hello","goodbye")

newdf <- rbind(df, de)

How to append rows to an R data frame


Update

Not knowing what you are trying to do, I'll share one more suggestion: Preallocate vectors of the type you want for each column, insert values into those vectors, and then, at the end, create your data.frame.

Continuing with Julian's f3 (a preallocated data.frame) as the fastest option so far, defined as:

# pre-allocate space
f3 <- function(n){
df <- data.frame(x = numeric(n), y = character(n), stringsAsFactors = FALSE)
for(i in 1:n){
df$x[i] <- i
df$y[i] <- toString(i)
}
df
}

Here's a similar approach, but one where the data.frame is created as the last step.

# Use preallocated vectors
f4 <- function(n) {
x <- numeric(n)
y <- character(n)
for (i in 1:n) {
x[i] <- i
y[i] <- i
}
data.frame(x, y, stringsAsFactors=FALSE)
}

microbenchmark from the "microbenchmark" package will give us more comprehensive insight than system.time:

library(microbenchmark)
microbenchmark(f1(1000), f3(1000), f4(1000), times = 5)
# Unit: milliseconds
# expr min lq median uq max neval
# f1(1000) 1024.539618 1029.693877 1045.972666 1055.25931 1112.769176 5
# f3(1000) 149.417636 150.529011 150.827393 151.02230 160.637845 5
# f4(1000) 7.872647 7.892395 7.901151 7.95077 8.049581 5

f1() (the approach below) is incredibly inefficient because of how often it calls data.frame and because growing objects that way is generally slow in R. f3() is much improved due to preallocation, but the data.frame structure itself might be part of the bottleneck here. f4() tries to bypass that bottleneck without compromising the approach you want to take.


Original answer

This is really not a good idea, but if you wanted to do it this way, I guess you can try:

for (i in 1:10) {
df <- rbind(df, data.frame(x = i, y = toString(i)))
}

Note that in your code, there is one other problem:

  • You should use stringsAsFactors if you want the characters to not get converted to factors. Use: df = data.frame(x = numeric(), y = character(), stringsAsFactors = FALSE)

Create an empty dataframe and append rows to it in R

You need to store the result of rbind back into AvsB in each loop:

datosA <- read_excel(archivo, col_names = TRUE, sheet = "Sheet1")
datosB <- read_excel(archivo, col_names = TRUE, sheet = "Sheet1")

AvsB <- data.frame()

for (x in datosA$'m/z') {
if (!(x %in% datosB$'m/z')) {
index <- match(x, datosA$'m/z')
AvsB <- rbind(AvsB, datosA[index,])
}
}

How to append rows as new columns of a dataframe R

One possibility involving dplyr and tidyr could be:

df %>%
mutate(grp = cumsum(!grepl("text", V1, fixed = TRUE))) %>%
gather(var, val, -grp) %>%
group_by(grp) %>%
mutate(var = paste0("V", row_number())) %>%
ungroup() %>%
spread(var, val) %>%
select(-grp)

V1 V2 V3 V4 V5 V6
<chr> <chr> <chr> <chr> <chr> <chr>
1 1234 text1 data1 data2 <NA> <NA>
2 2345 text1 text2 data3 data4 data5
3 3456 text1 data6 data7 <NA> <NA>

Or if you want to match your desired output exactly:

df %>%
group_by(grp = cumsum(!grepl("text", V1, fixed = TRUE))) %>%
mutate(grp2 = row_number()) %>%
ungroup() %>%
gather(var, val, -c(grp, grp2)) %>%
arrange(grp, grp2) %>%
group_by(grp) %>%
mutate(var = paste0("V", row_number())) %>%
ungroup() %>%
select(-grp2) %>%
spread(var, val) %>%
select(-grp)

V1 V2 V3 V4 V5 V6
<chr> <chr> <chr> <chr> <chr> <chr>
1 1234 data1 text1 data2 <NA> <NA>
2 2345 data3 text1 data4 text2 data5
3 3456 data6 text1 data7 <NA> <NA>

How to add row to dataframe?

You are trying to add a vector and rbind it with data frame which is not the best option. You better rbind a data.frame to data.frame.

So in your case better to do:

for (state in unique(data$state)) {
means<-rbind(means, data.frame(State=state,Mean=4)
}

Add a value as a new row to a dataframe but keep all other columns NA

A possible solution, based on dplyr. We first need to convert ID from numeric to character.

library(dplyr)

mydata %>%
mutate(ID = as.character(ID)) %>%
bind_rows(list(ID = "School 1"), .)

#> # A tibble: 6 × 3
#> ID subject age
#> <chr> <chr> <dbl>
#> 1 School 1 <NA> NA
#> 2 1 His 21
#> 3 2 Geo 24
#> 4 3 Geo 26
#> 5 4 His 23
#> 6 5 Geo 26

How can I add several NA's as rows to data frame?

Similar to GKi's solution but without rbind():

df[c(rep(NA, 4L), seq_len(nrow(df))), ]
# X1.3 X4.6 X7.9
# NA NA NA NA
# NA.1 NA NA NA
# NA.2 NA NA NA
# NA.3 NA NA NA
# 1 1 4 7
# 2 2 5 8
# 3 3 6 9


Related Topics



Leave a reply



Submit