私はRを学ぼうとしていますが、リストに追加する方法がわかりません。
これがPythonの場合。 。
#Python
vector = []
values = ['a','b','c','d','e','f','g']
for i in range(0,len(values)):
vector.append(values[i])
Rでこれをどうやってしますか?
#R Programming
> vector = c()
> values = c('a','b','c','d','e','f','g')
> for (i in 1:length(values))
+ #append value[i] to empty vector
これを行うにはいくつかの方法があります。それらのすべてが推奨されていません。 forループ内のオブジェクトに追加すると、反復ごとにオブジェクト全体がコピーされるため、多くの人が "Rは遅い"、または "Rループは避けるべきである"と言います。
# one way
for (i in 1:length(values))
vector[i] <- values[i]
# another way
for (i in 1:length(values))
vector <- c(vector, values[i])
# yet another way?!?
for (v in values)
vector <- c(vector, v)
# ... more ways
help("append")
はあなたの質問に答えて、あなたがこの質問を書くのにかかる時間を節約したでしょう(しかしあなたに悪い習慣を開発させたであろう)。 ;-)
vector <- c()
は空のベクトルではありません。それはNULL
です。空の文字ベクトルが必要な場合は、vector <- character()
を使用してください。
また、 BrodieG がコメントで指摘しているように、を絶対にを使用しなければならない場合は、少なくともループ全体の前にベクトル全体を事前に割り当てる必要があります。ベクトル.
set.seed(21)
values <- sample(letters, 1e4, TRUE)
vector <- character(0)
# slow
system.time( for (i in 1:length(values)) vector[i] <- values[i] )
# user system elapsed
# 0.340 0.000 0.343
vector <- character(length(values))
# fast(er)
system.time( for (i in 1:length(values)) vector[i] <- values[i] )
# user system elapsed
# 0.024 0.000 0.023
FWIW:pythonのappend()に似ています。
b <- 1
b <- c(b, 2)
いくつかの選択肢があります。
c(vector, values)
append(vector, values)
vector[(length(vector) + 1):(length(vector) + length(values))] <- values
最初のものは標準的なアプローチです。 2番目のものはあなたに最後以外のどこかに追加するオプションを与えます。最後のものは少しゆがんでいますが、vector
を変更するという利点があります(とはいえ、vector <- c(vector, values)
も簡単にできます)。
Rではベクトルを巡回する必要がないことに注意してください。あなたはそれら全体を操作することができます。
また、これはかなり基本的なものなので、the referencesをいくつか見てみるべきです。
OPフィードバックに基づくその他のオプション
for(i in values) vector <- c(vector, i)
@BrodieGが指摘したように、完全性を期すために、forループ内のベクトルに値を追加することは、実際にはRの哲学ではありません。あなたのコードを次のように書き換えることができないかどうかを確認してください。
ouput <- sapply(values, function(v) return(2*v))
出力は戻り値のベクトルになります。 valuesがベクトルではなくリストの場合はlapply
を使うこともできます。
たとえば、結果を取得するために必要な反復回数がわからない場合など、ループを使用しなければならないことがあります。例としてwhileループを取ります。以下は絶対に避けるべき方法です。
a=numeric(0)
b=1
system.time(
{
while(b<=1e5){
b=b+1
a<-c(a,pi)
}
}
)
# user system elapsed
# 13.2 0.0 13.2
a=numeric(0)
b=1
system.time(
{
while(b<=1e5){
b=b+1
a<-append(a,pi)
}
}
)
# user system elapsed
# 11.06 5.72 16.84
Rは追加するたびにベクトルをコピーするので、これらは非常に非効率的です。
追加する最も効率的な方法はindexを使うことです。今回は1e7回繰り返しますが、それでもc
よりはるかに高速です。
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[length(a)+1]=pi
}
}
)
# user system elapsed
# 5.71 0.39 6.12
これは許容範囲です。 [
を[[
に置き換えることで、少し速くすることができます。
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[[length(a)+1]]=pi
}
}
)
# user system elapsed
# 5.29 0.38 5.69
length
は時間がかかることに気付いたかもしれません。 length
をカウンタで置き換えると:
a=numeric(0)
b=1
system.time(
{
while(b<=1e7){
a[[b]]=pi
b=b+1
}
}
)
# user system elapsed
# 3.35 0.41 3.76
他のユーザーが言ったように、ベクトルを事前に割り当てることは非常に役に立ちます。しかし、結果を得るのに必要なループの数がわからない場合、これは速度とメモリ使用量の間のトレードオフです。
a=rep(NaN,2*1e7)
b=1
system.time(
{
while(b<=1e7){
a[[b]]=pi
b=b+1
}
a=a[!is.na(a)]
}
)
# user system elapsed
# 1.57 0.06 1.63
中間的な方法は、結果のブロックを徐々に追加することです。
a=numeric(0)
b=0
step_count=0
step=1e6
system.time(
{
repeat{
a_step=rep(NaN,step)
for(i in seq_len(step)){
b=b+1
a_step[[i]]=pi
if(b>=1e7){
a_step=a_step[1:i]
break
}
}
a[(step_count*step+1):b]=a_step
if(b>=1e7) break
step_count=step_count+1
}
}
)
#user system elapsed
#1.71 0.17 1.89
> vec <- c(letters[1:3]) # vec <- c("a","b","c") ; or just empty vector: vec <- c()
> values<- c(1,2,3)
> for (i in 1:length(values)){
print(paste("length of vec", length(vec)));
vec[length(vec)+1] <- values[i] #Appends value at the end of vector
}
[1] "length of vec 3"
[1] "length of vec 4"
[1] "length of vec 5"
> vec
[1] "a" "b" "c" "1" "2" "3"
Rでは、このようにして試すことができます。
X = NULL
X
# NULL
values = letters[1:10]
values
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
X = append(X,values)
X
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
X = append(X,letters[23:26])
X
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "w" "x" "y" "z"