R: losing column names when adding rows to an empty data frame

筅森魡賤 提交于 2019-11-28 05:37:39
juba

The rbind help pages specifies that :

For ‘cbind’ (‘rbind’), vectors of zero length (including ‘NULL’) are ignored unless the result would have zero rows (columns), for S compatibility. (Zero-extent matrices do not occur in S3 and are not ignored in R.)

So, in fact, a is ignored in your rbind instruction. Not totally ignored, it seems, because as it is a data frame the rbind function is called as rbind.data.frame :

rbind.data.frame(c(5,6))
#  X5 X6
#1  5  6

Maybe one way to insert the row could be :

a[nrow(a)+1,] <- c(5,6)
a
#  one two
#1   5   6

But there may be a better way to do it depending on your code.

Raffael

was almost surrendering to this issue.

1) create data frame with stringsAsFactor set to FALSE or you run straight into the next issue

2) don't use rbind - no idea why on earth it is messing up the column names. simply do it this way:

df[nrow(df)+1,] <- c("d","gsgsgd",4)

df <- data.frame(a = character(0), b=character(0), c=numeric(0))

df[nrow(df)+1,] <- c("d","gsgsgd",4)

#Warnmeldungen:
#1: In `[<-.factor`(`*tmp*`, iseq, value = "d") :
#  invalid factor level, NAs generated
#2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") :
#  invalid factor level, NAs generated

df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F)

df[nrow(df)+1,] <- c("d","gsgsgd",4)

df
#  a      b c
#1 d gsgsgd 4

Workaround would be:

a <- rbind(a, data.frame(one = 5, two = 6))

?rbind states that merging objects demands matching names:

It then takes the classes of the columns from the first data frame, and matches columns by name (rather than by position)

FWIW, an alternative design might have your functions building vectors for the two columns, instead of rbinding to a data frame:

ones <- c()
twos <- c()

Modify the vectors in your functions:

ones <- append(ones, 5)
twos <- append(twos, 6)

Repeat as needed, then create your data.frame in one go:

a <- data.frame(one=ones, two=twos)

One way to make this work generically and with the least amount of re-typing the column names is the following. This method doesn't require hacking the NA or 0.

rs <- data.frame(i=numeric(), square=numeric(), cube=numeric())
for (i in 1:4) {
    calc <- c(i, i^2, i^3)
    # append calc to rs
    names(calc) <- names(rs)
    rs <- rbind(rs, as.list(calc))
}

rs will have the correct names

> rs
    i square cube
1   1      1    1
2   2      4    8
3   3      9   27
4   4     16   64
> 

Another way to do this more cleanly is to use data.table:

> df <- data.frame(a=numeric(0), b=numeric(0))
> rbind(df, list(1,2)) # column names are messed up
>   X1 X2
> 1  1  2

> df <- data.table(a=numeric(0), b=numeric(0))
> rbind(df, list(1,2)) # column names are preserved
   a b
1: 1 2

Notice that a data.table is also a data.frame.

> class(df)
"data.table" "data.frame"

You can do this:

give one row to the initial data frame

 df=data.frame(matrix(nrow=1,ncol=length(newrow))

add your new row and take out the NAS

newdf=na.omit(rbind(newrow,df))

but watch out that your newrow does not have NAs or it will be erased too.

Cheers Agus

I use the following solution to add a row to an empty data frame:

d_dataset <- 
  data.frame(
    variable = character(),
    before = numeric(),
    after = numeric(),
    stringsAsFactors = FALSE)

d_dataset <- 
  rbind(
    d_dataset,
      data.frame(
        variable = "test",
        before = 9,
        after = 12,
        stringsAsFactors = FALSE))  

print(d_dataset)

variable before after  
1     test      9    12

HTH.

Kind regards

Georg

Daniel

Instead of constructing the data.frame with numeric(0) I use as.numeric(0).

a<-data.frame(one=as.numeric(0), two=as.numeric(0))

This creates an extra initial row

a
#    one two
#1   0   0

Bind the additional rows

a<-rbind(a,c(5,6))
a
#    one two
#1   0   0
#2   5   6

Then use negative indexing to remove the first (bogus) row

a<-a[-1,]
a

#    one two
#2   5   6

Note: it messes up the index (far left). I haven't figured out how to prevent that (anyone else?), but most of the time it probably doesn't matter.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!