Connie
Connie

Reputation: 89

R: How to add a row that has different number of columns than the rest of the data frame?

I have a dataframe that looks like this:

set <- data.frame("id"=c("one", "two","three"), "line_number"=c("1", "2", "3"), 
              "content_type"=c("paragraph", "paragraph","paragraph"), 
              "text"=c("this is a sample","first batch is:", "second batch is:"), 
              "section"=c("introduction","content","summary"))

So it looks like:

  set(view)
  id       line_number      content_type     text                   section
  one           1            paragraph       this is a sample     introduction
  two           2            paragraph       first batch is:        content
  three         3            paragraph       second batch is:       summary

I want to add one row on top of this data frame, which only has content in one column, now it looks like:

  set(view)
  id       line_number      content_type     text                   section
                                             Sample Report
  one           1            paragraph       this is a sample     introduction
  two           2            paragraph       first batch is:        content
  three         3            paragraph       second batch is:       summary

And R can just automatically fill in NA wherever it's needed.

I try to use rbind but it won't let me do it because numbers of columns do not match. Is there other way to do it? Maybe a loop?

Thank you! I really appreciate it.

Upvotes: 1

Views: 1732

Answers (3)

user3487564
user3487564

Reputation: 149

Other alternatives to what has already been given:

set <- data.frame("id"=c("one", "two","three"), "line_number"=c("1", "2", "3"), 
              "content_type"=c("paragraph", "paragraph","paragraph"), 
              "text"=c("this is a sample","first batch is:", "second batch is:"), 
              "section"=c("introduction","content","summary"), stringsAsFactors = FALSE)
x <- data.frame(text = "Sample Report", stringsAsFactors = FALSE)

using dplyr

library(dplyr)
d1 <- full_join(set,x)
d1 <- d1 %>% arrange(!is.na(line_number),line_number)

The second step will help ensure you get your "Sample Report" in the first row.

using base R

d2 <- merge(set,x,all = T)
d2 <- d2[order(d2$line_number,na.last=F),]

Again, the second line of code above will help ensure you get your "Sample Report" in the first row. In both cases, the merging variable is not explicitly stated (but R by default takes the variables that is common to both datasets i.e. the "text" variable).

Upvotes: 1

moodymudskipper
moodymudskipper

Reputation: 47310

base R

set2[setdiff(names(set),names(set2))] <- NA
rbind(set2,set)
#               text    id line_number content_type      section
# 1    Sample Report  <NA>        <NA>         <NA>         <NA>
# 2 this is a sample   one           1    paragraph introduction
# 3  first batch is:   two           2    paragraph      content
# 4 second batch is: three           3    paragraph      summary

or for a one liner that doesn't change set2:

rbind('[<-'(set2,setdiff(names(set),names(set2)),value= NA),set)

dplyr

dplyr::bind_rows(set2,set)
#               text    id line_number content_type      section
# 1    Sample Report  <NA>        <NA>         <NA>         <NA>
# 2 this is a sample   one           1    paragraph introduction
# 3  first batch is:   two           2    paragraph      content
# 4 second batch is: three           3    paragraph      summary

data.table

data.table::rbindlist(list(set2,set),fill=TRUE)
#                text    id line_number content_type      section
# 1:    Sample Report    NA          NA           NA           NA
# 2: this is a sample   one           1    paragraph introduction
# 3:  first batch is:   two           2    paragraph      content
# 4: second batch is: three           3    paragraph      summary

note on column order

The column order is given by the first data.frame, that's why column text was moved to the left. Add [names(set)] to any answer to get the original order back.

data

set <- data.frame("id"=c("one", "two","three"), "line_number"=c("1", "2", "3"), 
                  "content_type"=c("paragraph", "paragraph","paragraph"), 
                  "text"=c("this is a sample","first batch is:", "second batch is:"), 
                  "section"=c("introduction","content","summary"))

set2 <- data.frame(text ="Sample Report")   

Upvotes: 1

Mike
Mike

Reputation: 4370

This should do it

set <- data.frame("id"=c("one", "two","three"), "line_number"=c("1", "2", "3"), 
                  "content_type"=c("paragraph", "paragraph","paragraph"), 
                  "text"=c("this is a sample","first batch is:", "second batch is:"), 
                  "section"=c("introduction","content","summary"), stringsAsFactors = FALSE)
x <- data.frame(text = "Sample Report", stringsAsFactors = FALSE)
dplyr::bind_rows(set,x )

Upvotes: 1

Related Questions