2017-06-05 19 views
0

私はStudent1からStudent 29という29のデータフレームを持っています。これらの29個のデータフレームのそれぞれには変数Name、nationality、Membership.number終わり。例えばStudent1にはName.1、Nationality.1、Membership.number1、Student29にはName.29などが含まれています。R - ネストループを使用して、複数のデータフレームで複数の列の名前を変更します。

これらの変数名の末尾にある数字を削除して標準化しようとしています。私はRの新機能ですが、これを試して自動化するために次のコードをまとめました。

for (j in 1:29) { 
for (i in 1:3) { 
    oldnames = c(paste('Name', i, sep="."), paste('Nationality', i, sep="."), paste('Membership.number', i, sep=".")) 
    newnames = c("Name", "Nationality", "Membership.number") 
    names(paste("Student",j,sep=""))[names(paste("Student",j,sep=""))==oldnames[i]]=newnames[i] 
    } 
} 

これは私が欲しいものを達成するために近いと表示され、それが必要として、私はペーストの場所(「学生」、=「」J、9月)にSTUDENT1を挿入した場合、単一のデータフレームのために動作しますが、 pasteが( "Student"、j、sep = "")コードは "代入対象が非言語オブジェクトに展開"するために失敗しているようです。私はここで間違っている何か簡単ですか?

答えて

0

は、問題はあなたのコードが効果的のようなものをやっているのでpaste()は、文字列を返すということです。もちろん、

names("Student1")[names("Student1")==oldnames[i]] = newnames[i] 

しかし、文字列"Student1"はあなたのデータを含む変数Student1と同じではありませんフレーム、これはあなたを非常に遠くに取得しません。エラーメッセージは少し混乱しますが、最終的には割り当てることができないものに割り当てることを意味しています。

最も簡単な解決策は、(文字列"Student1"のような)変数名を表す文字列をとる関数get()assign()を利用すると、あなたが取得し、変数を割り当てることができるようにすることです。たとえば、これはStudent1のいずれかの列名前を変更します:定義を私はoldnames定義を固定

for (j in 1:29) { 
    oldnames = c(paste('Name', j, sep="."), 
       paste('Nationality', j, sep="."), 
       paste('Membership.number', j, sep=".")) 
    newnames = c("Name", "Nationality", "Membership.number") 
    dfname = paste("Student", j, sep="") 
    df = get(dfname) 
    for (i in 1:3) { 
     names(df)[names(df) == oldnames[i]] = newnames[i] 
    } 
    assign(dfname, df) 
} 

注意が代わりにijを使用するようにして移動:だから

dfname = "Student1" 
df = get(dfname) 
names(df)[names(df)=="Name.1"] = "Name" 
assign(dfname, df) 

を、あなたが書くことができますそれは内部ループの外にjだけに依存していました。ここで注意すべき点の1つは、これは「トップレベル」(つまり、Rプロンプトで入力)でのみ機能することです。それを関数に入れた場合、を指定する必要があるので、assign()は扱いにくくなります。に変数を割り当てます(残りのグローバル変数で、関数内など)。

このコードは改善することができます。あなたが実際に書くことができることを意味している

oldnames = paste(c("Name","Nationality","Membership.number"), j, sep=".") 

:それはoldnamesのあなたの定義のように書き換えることができることが判明し

newnames = c("Name","Nationality","Membership.number") 
oldnames = paste(newnames, j, sep=".") 

あなたはさらに一歩進み、機能matchを使用することができます。この関数は、第2引数内の第1引数の各要素のインデックスを取得し、names()ベクトル内のすべてのoldnamesの位置を同時に取得するために使用できます。見つけるとベクトルは非常に一般的なR技法であるの値を置き換えるためにmatchの使用の

for (j in 1:29) { 
    newnames = c("Name","Nationality","Membership.number") 
    oldnames = paste(newnames, j, sep=".") 
    dfname = paste("Student", j, sep="") 
    df = get(dfname) 
    names(df)[match(oldnames, names(df))] = newnames 
    assign(dfname, df) 
} 

このソート:次に、あなたも内側のループを必要としません。

最後に、データフレームに他の列がない場合(実際には、ピリオドとすべての名前の最後からいくつかの数字で構成される接尾辞をすべて削除するだけです)、Rの一般的なトリック正規表現を使用して名前を変更するためにsub()を使用することです:

for (j in 1:29) { 
    newnames = c("Name","Nationality","Membership.number") 
    oldnames = paste(newnames, j, sep=".") 
    dfname = paste("Student", j, sep="") 
    df = get(dfname) 
    names(df) = sub("\\.[0-9]+$", "", names(df)) 
    assign(dfname, df) 
} 

、Rで、正規表現でバックスラッシュを二重にする必要があります注ので、上記の"\\."を期間と一致します。私はこのsubベースのテクニックは、列名の束に不要な接頭辞と接尾辞を持つデータセットを整理する際に常に使用します。

ハッピーRING!

+0

これは素晴らしいことですが、私の質問に対する答えと同様に、私のコードをクリーンアップするためのいくつかの便利なヒントと修正があります。私はRの2日目にしかいないので、これは錆びている部分をクリアするのに役立ちます!とても有難い。 – diggergoat

関連する問題