31

ループを使用してこれを解決することはできますが、コードをよりR風にするために、ベクトルで考えようとしています。

名前のリストがあります。形式はfirstname_lastnameです。このリストから、名だけの別のリストを取得したいと思います。私はこれを行う方法について頭を悩ませているようには見えません。データの例を次に示します。

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
tsplit <- strsplit(t,"_")

これは次のようになります:

> tsplit
[[1]]
[1] "bob"   "smith"

[[2]]
[1] "mary" "jane"

[[3]]
[1] "jose"  "chung"

[[4]]
[1] "michael" "marx"   

[[5]]
[1] "charlie" "ivan"   

次のようなループを使用して、必要なものを取得できます。

for (i in 1:length(tsplit)){
    if (i==1) {t_out <- tsplit[[i]][1]} else{t_out <- append(t_out, tsplit[[i]][1])} 
}

それは私にこれを与えるでしょう:

t_out
[1] "bob"     "mary"    "jose"    "michael" "charlie"

では、どうすればループなしでこれを行うことができますか?

4

10 に答える 10

43

そしてもう1つのアプローチ:

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
pieces <- strsplit(t,"_")
sapply(pieces, "[", 1)

つまり、最後の行は、リストの各コンポーネントの最初の要素を抽出し、それを単純化してベクトルにします。

これはどのように作動しますか?さて、あなたは別の書き方を理解する必要があります。x[1]つまり、サブセット化を行う"["(x, 1)という関数があります。呼び出しは、元のリストの要素ごとにこの関数を1回呼び出し、list要素と1の2つの引数を渡します[sapply

他のアプローチに対するこのアプローチの利点は、分割を再計算することなく、リストから複数の要素を抽出できることです。たとえば、姓は。になりますsapply(pieces, "[", 2)。このイディオムに慣れれば、非常に読みやすくなります。

于 2009-08-31T03:20:05.753 に答える
26

使用できますapply(またはsapply

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
f <- function(s) strsplit(s, "_")[[1]][1]
sapply(t, f)

bob_smith    mary_jane   jose_chung michael_marx charlie_ivan 

       "bob"       "mary"       "jose"    "michael"    "charlie" 

参照:Rでの「適用」の簡単な紹介

于 2009-08-31T01:16:25.470 に答える
10

どうですか:

tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
fnames <- gsub("(_.*)$", "", tlist)
# _.* matches the underscore followed by a string of characters
# the $ anchors the search at the end of the input string
# so, underscore followed by a string of characters followed by the end of the input string

正規表現アプローチの場合?

于 2009-08-31T02:33:51.370 に答える
9

どうですか:

t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")

sub("_.*", "", t)
于 2010-01-22T18:29:22.177 に答える
7

これが最もエレガントな解決策ではないかと思いますが、ループに勝るものはありません。

t.df <- data.frame(tsplit)
t.df[1, ]

リストをデータフレームに変換することは、私が望むことをリストに実行させる唯一の方法です。リストの扱い方を実際に理解している人の回答を読むのを楽しみにしています。

于 2009-08-31T01:12:14.353 に答える
4

あなたはほとんどそれを持っていました。それは本当にただの問題です

  1. 関数の1つを使用*applyして既存のリストをループする場合、私は多くの場合、最初に開始しlapply、場合によっては次のように切り替えます。sapply
  2. リスト要素の1つを一度に操作する無名関数を追加します
  3. あなたはそれがそうであったことをすでに知っていました、そしてあなたは答えの最初の用語を選ぶためstrsplit(string, splitterm)に奇妙なものが必要であることを知っていました[[1]][1]
  4. 好みの変数の名前から始めて、すべてをまとめるだけです(または、tまたはc友達から離れているため)

これは

> tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan") 
> fnames <- sapply(tlist, function(x) strsplit(x, "_")[[1]][1]) 
> fnames 
  bob_smith    mary_jane   jose_chung michael_marx charlie_ivan   
      "bob"       "mary"       "jose"    "michael"    "charlie" 
>
于 2009-08-31T01:09:33.947 に答える
3

あなたが使用することができますunlist()

> tsplit <- unlist(strsplit(t,"_"))
> tsplit
 [1] "bob"     "smith"   "mary"    "jane"    "jose"    "chung"   "michael"
 [8] "marx"    "charlie" "ivan"   
> t_out <- tsplit[seq(1, length(tsplit), by = 2)]
> t_out
[1] "bob"     "mary"    "jose"    "michael" "charlie"

奇数インデックスのエントリのみを引き出すためのより良い方法があるかもしれませんが、いずれの場合もループはありません。

于 2009-08-31T01:10:16.880 に答える
2

そして、brentonkのリストにない例に基づくもう1つのアプローチ...

tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
tsplit <- unlist(strsplit(tlist,"_"))
fnames <- tsplit[seq(1:length(tsplit))%%2 == 1]

于 2009-08-31T02:56:25.093 に答える
1

次のunlist()ベースのメソッドを使用します。

> t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
> tsplit <- strsplit(t,"_")
> 
> x <- matrix(unlist(tsplit), 2)
> x[1,]
[1] "bob"     "mary"    "jose"    "michael" "charlie"

この方法の大きな利点は、名前の同等の問題を同時に解決できることです。

> x[2,]
[1] "smith" "jane"  "chung" "marx"  "ivan" 

firstname_lastname欠点は、すべての名前が構造に準拠していることを確認する必要があることです。そうでない場合、このメソッドは機能しなくなります。

于 2012-09-07T18:42:07.753 に答える
0

最初に指定された元のtsplitリストオブジェクトから、このコマンドは次のことを行います。

unlist(lapply(tsplit,function(x) x[1]))

すべてのリスト要素の最初の要素を抽出してから、リストをベクトルに変換します。最初に行列のリストを解除してから、最初の列を抽出することもできますが、すべてのリスト要素の長さが同じであるという事実に依存しています。出力は次のとおりです。

> tsplit

[[1]]
[1] "bob"   "smith"

[[2]]
[1] "mary" "jane"

[[3]]
[1] "jose"  "chung"

[[4]]
[1] "michael" "marx"   

[[5]]
[1] "charlie" "ivan"   

> lapply(tsplit,function(x) x[1])

[[1]]
[1] "bob"

[[2]]
[1] "mary"

[[3]]
[1] "jose"

[[4]]
[1] "michael"

[[5]]
[1] "charlie"

> unlist(lapply(tsplit,function(x) x[1]))

[1] "bob"     "mary"    "jose"    "michael" "charlie"
于 2013-02-28T10:53:22.230 に答える