web-dev-qa-db-ja.com

R:空のデータフレームに行を追加すると列名が失われる

Rから始めたばかりで、奇妙な動作に遭遇しました。最初の行を空のデータフレームに挿入すると、元の列名が失われます。

例:

a<-data.frame(one = numeric(0), two = numeric(0))
a
#[1] one two
#<0 rows> (or 0-length row.names)
names(a)
#[1] "one" "two"
a<-rbind(a, c(5,6))
a
#  X5 X6
#1  5  6
names(a)
#[1] "X5" "X6"

ご覧のとおり、列名oneおよびtwoX5およびX6に置き換えられました。

誰かがこれがなぜ起こるのか教えてもらえますか?列名を失うことなくこれを行う正しい方法はありますか?

散弾銃の解決策は、補助ベクトルに名前を保存し、データフレームでの作業が終了したらそれらを追加し直すことです。

ありがとう

環境:

いくつかのデータを収集し、それらをパラメーターとして受け取ったデータフレームに新しい行として追加する関数を作成しました。データフレームを作成し、データソースを反復処理し、data.frameを各関数呼び出しに渡して、その結果で埋めます。

59
cdmihai

rbindヘルプページでは、次のことが指定されています。

「cbind」(「rbind」)の場合、S互換性のため、結果にゼロ行(列)が含まれない限り、長さがゼロのベクトル(「NULL」を含む)は無視されます。 (ゼロエクステント行列はS3では発生せず、Rでは無視されません。)

したがって、実際には、a命令ではrbindは無視されます。それはデータフレームであるため、rbind関数はrbind.data.frame

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

行を挿入する1つの方法は次のとおりです。

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

ただし、コードによってはより良い方法があります。

33
juba

この問題にほとんど降伏していた。

1)stringsAsFactorFALSEに設定してデータフレームを作成するか、次の問題に直行します

2)rbindを使用しないでください-いったいなぜ列名を台無しにしているのかわかりません。単純に次のようにします:

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
12
Raffael

回避策は次のとおりです。

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

?rbindは、オブジェクトのマージには一致する名前が必要であることを示しています。

次に、最初のデータフレームから列のクラスを取得し、(位置ではなく)名前で列を照合します

8
Roman Luštrik

FWIW、代替設計では、データフレームにrbindingする代わりに、2つの列のベクトルを構築する関数を使用できます。

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

関数内のベクトルを変更します。

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

必要に応じて繰り返してから、data.frameを一度に作成します。

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

これを一般的に機能させ、列名の再入力を最小限に抑える1つの方法は次のとおりです。この方法では、NAまたは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には正しい名前が付けられます

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

これをよりきれいに行う別の方法は、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

Data.tableはdata.frameでもあることに注意してください。

> class(df)
"data.table" "data.frame"
2
Steve Lihn

あなたはこれを行うことができます:

最初のデータフレームに1行を与える

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

新しい行を追加して、NASを取り出します

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

ただし、newrowにはNAがないか、消去されます。

乾杯アグス

1
Agus camacho

次のソリューションを使用して、空のデータフレームに行を追加します。

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。

敬具

ゲオルグ

0
Georg