data.frameに列を追加する


115

以下のdata.frameがあります。h_no最初の一連のh_no 1,2,3,4がクラス1、2番目の一連のh_no(1〜7)がクラス2になるように、列1()に従ってデータを分類する列を追加します。最後の列に示されているような。

h_no  h_freq  h_freqsq
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3

回答:


155

さまざまな手法を使用して、データに列を追加できます。以下の引用は、関連するヘルプテキストの「詳細」セクションから引用しています[[.data.frame

データフレームには、いくつかのモードでインデックスを付けることができます。単一のベクトルインデックス(または)と一緒に使用する[と、それらはリストであるかのようにデータフレームにインデックスを付けます。[[x[i]x[[i]]

my.dataframe["new.col"] <- a.vector
my.dataframe[["new.col"]] <- a.vector

のdata.frameメソッドは$xリストとして扱います

my.dataframe$new.col <- a.vector

[および[[が2つのインデックス(x[i, j]およびx[[i, j]])と共に使用される場合、それらは行列のインデックス付けのように機能します

my.dataframe[ , "new.col"] <- a.vector

のメソッドはdata.frame、列と行のどちらを使用しているかを指定しない場合は、列を意味すると見なします。


あなたの例では、これはうまくいくはずです:

# make some fake data
your.df <- data.frame(no = c(1:4, 1:7, 1:5), h_freq = runif(16), h_freqsq = runif(16))

# find where one appears and 
from <- which(your.df$no == 1)
to <- c((from-1)[-1], nrow(your.df)) # up to which point the sequence runs

# generate a sequence (len) and based on its length, repeat a consecutive number len times
get.seq <- mapply(from, to, 1:length(from), FUN = function(x, y, z) {
            len <- length(seq(from = x[1], to = y[1]))
            return(rep(z, times = len))
         })

# when we unlist, we get a vector
your.df$group <- unlist(get.seq)
# and append it to your original data.frame. since this is
# designating a group, it makes sense to make it a factor
your.df$group <- as.factor(your.df$group)


   no     h_freq   h_freqsq group
1   1 0.40998238 0.06463876     1
2   2 0.98086928 0.33093795     1
3   3 0.28908651 0.74077119     1
4   4 0.10476768 0.56784786     1
5   1 0.75478995 0.60479945     2
6   2 0.26974011 0.95231761     2
7   3 0.53676266 0.74370154     2
8   4 0.99784066 0.37499294     2
9   5 0.89771767 0.83467805     2
10  6 0.05363139 0.32066178     2
11  7 0.71741529 0.84572717     2
12  1 0.10654430 0.32917711     3
13  2 0.41971959 0.87155514     3
14  3 0.32432646 0.65789294     3
15  4 0.77896780 0.27599187     3
16  5 0.06100008 0.55399326     3

列を追加する最後の2つの方法の違いは何ですか?
huon

2
@ huon-dbauppコンマを使用したメソッドは明示的であり、行列でも機能しますが、最後のものはdata.framesでのみ機能します。コンマが指定されていない場合、Rは列を意味すると見なします。
RomanLuštrik15年

12

簡単:データフレームはA

b <- A[,1]
b <- b==1
b <- cumsum(b)

次に、列bを取得します。


素敵で短い。最後の要素を変更するだけでcumsum(b) -> b、結果ではなく、元のデータフレームに列として直接追加されますA$groups <- cumsum(b)
A5C1D2H2I1M1N2O1R2T1 2012

cumsum(b)長さ3のベクトルが表示されますか、それとも何か不足していますか?
RomanLuštrik2012

@RomanLuštrik、cumsumがこの場合どのように機能するかを説明するdbauppのソリューションを参照してください。
A5C1D2H2I1M1N2O1R2T1

2
@RomanLuštrik、このソリューションは1行で非常にうまく書き直すことができます。your.dfデータを使用してyour.df$group = cumsum(your.df[, 1]==1)、新しいグループ列を取得するだけです。
A5C1D2H2I1M1N2O1R2T1 2012

7

私が質問を正しく理解している場合は、h_noが増加しないことを検出し、を増加させclassます。(この問題の解決方法を順を追って説明します。最後に自己完結型の関数があります。)

ワーキング

ここでは、h_no列のみを考慮しているため、データフレームから列を抽出できます。

> h_no <- data$h_no

いつh_no上昇しないかを検出したいのですが、これは、連続する要素間の差が負またはゼロのどちらであるかを調べることで実行できます。Rは、diff差のベクトルを与える関数を提供します。

> d.h_no <- diff(h_no)
> d.h_no
 [1]  1  1  1 -3  1  1  1  1  1  1 -6  1  1  1

それが得られたら、ポジティブでないものを見つけるのは簡単です。

> nonpos <- d.h_no <= 0
> nonpos
 [1] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
[13] FALSE FALSE

Rに、TRUEそしてFALSE基本的に同じである10、我々はの累積和を取得するのであればnonpos、それは(ほとんど)適切なスポットに1だけ増加します。cumsum(基本的に反対である関数がdiff)これを行うことができます。

> cumsum(nonpos)
 [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2

しかし、2つの問題があります。数値が小さすぎることです。また、最初の要素がありません(最初のクラスには4つあるはずです)。

最初の問題は簡単に解決されます1+cumsum(nonpos)。そして、1最初の要素は常にクラスにあるので、2番目は単にベクトルの前にa を追加する必要があります1

 > classes <- c(1, 1 + cumsum(nonpos))
 > classes
  [1] 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3

これで、それをデータフレームに戻すことができますcbindclass=構文を使用して、列にclass見出しを付けることができます)。

 > data_w_classes <- cbind(data, class=classes)

そしてdata_w_classes今、結果が含まれています。

最終結果

行を一緒に圧縮し、すべてを関数にまとめて使いやすくすることができます。

classify <- function(data) {
   cbind(data, class=c(1, 1 + cumsum(diff(data$h_no) <= 0)))
}

または、classが要因であることは理にかなっているので:

classify <- function(data) {
   cbind(data, class=factor(c(1, 1 + cumsum(diff(data$h_no) <= 0))))
}

次のような関数を使用します。

> classified <- classify(data) # doesn't overwrite data
> data <- classify(data) # data now has the "class" column

(この問題を解決するこの方法は、一般的にRで推奨される明示的な反復を回避し、多数の中間ベクトルやリストなどを生成することを回避するため、優れています。また、1行で記述する方法も少し整然としています:))


2

ローマンの答えに加えて、このようなものはもっと簡単かもしれません。現在、Rにアクセスできないため、テストしていません。

# Note that I use a global variable here
# normally not advisable, but I liked the
# use here to make the code shorter
index <<- 0
new_column = sapply(df$h_no, function(x) {
  if(x == 1) index = index + 1
  return(index)
})

関数はの値を反復処理し、n_ho常に現在の値が属するカテゴリを返します。の値1が検出された場合、グローバル変数を増やしてindex続行します。


私はグローバル変数を使ったハックが好きです。だからシッシュ。:P
RomanLuštrik2012

2

Rのデータフレームに列を追加する最も簡単な方法は、「c​​bind」を使用することだと思います。以下の例:

    myDf = data.frame(index=seq(1,10,1), Val=seq(1,10,1))
    newCol= seq(2,20,2)
    myDf = cbind(myDf,newCol)


0

(グループの数識別に基づくアプローチxではmapply()とその長さymapply

mytb<-read.table(text="h_no  h_freq  h_freqsq group
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3", header=T, stringsAsFactors=F)
mytb$group<-NULL

positionsof1s<-grep(1,mytb$h_no)

mytb$newgroup<-unlist(mapply(function(x,y) 
  rep(x,y),                      # repeat x number y times
  x= 1:length(positionsof1s),    # x is 1 to number of nth group = g1:g3
  y= c( diff(positionsof1s),     # y is number of repeats of groups g1 to penultimate (g2) = 4, 7
        nrow(mytb)-              # this line and the following gives number of repeat for last group (g3)
          (positionsof1s[length(positionsof1s )]-1 )  # number of rows - position of penultimate group (g2) 
      ) ) )
mytb
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.