2016-08-15 3 views
1

私はさまざまな種類のリストであるオブジェクトのRリストを持っています。カテゴリが「内部」のすべてのオブジェクトの「コスト」値が必要です。これを達成する良い方法は何ですか?Rサブリスト付きリスト:規則に一致するすべての要素を配列に抽出します

私は

my_dataframe$cost[my_dataframe$category == "internal"] 

リストについては、類似したイディオムは何のようなものを行っていると思いますデータフレームを持っていた場合は?

mylist<-list(list(category="internal",cost=2), 
list(category="bar",cost=3),list(category="internal",cost=4), 
list(category='foo',age=56)) 

ここで私はc(2,4)を取得したいと思います。このようなサブセットは動作しません:

mylist[mylist$category == "internal"] 

私がすることで、この部分を行うことができます。

temp<-sapply(mylist,FUN = function(x) x$category=="internal") 
mylist[temp] 
[[1]] 
[[1]]$category 
[1] "internal" 

[[1]]$cost 
[1] 2 


[[2]] 
[[2]]$category 
[1] "internal" 

[[2]]$cost 
[1] 4 

しかし、私は(例えば)など、それらを合計することができるようにどのように私は、コストを得るのですか?私はこれを試してみましたが、あまり役に立ちません。

unlist(mylist[temp]) 
    category  cost category  cost 
"internal"  "2" "internal"  "4" 

私がしたいことをするためのきちんとしたコンパクトなイディオムはありますか?

答えて

3

あなたが探しているイディオムは、抽出されたベクトルのリストを返します。そうでない場合は、それが存在し、NULLすべき

sapply(mylist, "[[", "cost") 

です。

[[1]] 
[1] 2 

[[2]] 
[1] 3 

[[3]] 
[1] 4 

[[4]] 
NULL 

内部的なカテゴリの合計が必要な場合は、ベクターが必要であると仮定して、以下を実行できます。

sum(sapply(mylist[temp], "[[", "cost")) 

そして、あなたは同じ結果のリストが欲しい場合は、Rについての美しいが、挑戦的な物事の

sapply(mylist,function(x) x[x$category == "internal"]$cost) 

いずれかを行うことができ、同じ言語を表現するために非常に多くの方法があるということです。

sapplylapplyを交換することができますが、リストは単なる異種のベクトルであることに注意してください。以下はまた6を返します。

do.call("sum",lapply(mylist, function(x) x[x[["category"]] == "internal"]$cost)) 
+0

ありがとうございます!それは動作します。あなたは[[作品はどうですか?それは演算子ですか? –

+0

これはRの3つの抽出演算子の1つです。一般に '['と '[[' 'ベクトルには同様の関数がありますが、リストなどの再帰的ベクトルでは異なる働きをします。上記のコードの最後の行に加えて、 'do.call(" sum "、lapply(mylist、function(x)x [x [[" category "]] ==" internal "] [" cost "] )() ")")は動作しませんが、do.call( "sum"、lapply(mylist、function(x)x [x [[カテゴリ "]] =="内部 " 'うまくいく。 – shayaa

2

このようなものを試すことができます。すべてのサブリストのカテゴリは、「内部」であれば、コストを取得し、そうでない場合はNULLを返すときにunlist結果は無視される。

sum(unlist(lapply(mylist, function(x) if(x$category == "internal") x$cost))) 
# [1] 6 

安全な方法は、categoryがでサブリストに存在するかどうかもチェックすることですcategoryの長さをチェック:

sum(unlist(lapply(mylist, function(x) if(length(x$category) && x$category == "internal") x$cost))) 
# [1] 6 

サブリストはcategoryフィールドが含まれていない場合、これはエラーを上げる回避します。

+0

とにかくあなたが 'unlist'を使っているので' lapply'を使うだけでしょうか? – Sumedh

+0

@Sumedhはい。リストにNULLがあるときに単純化が機能しないのはなぜか分かりません。 – Psidom

+1

@Psidom - length(0)のようなオブジェクトは、length(1)オブジェクトとともにベクトルに強制変換できません。 – thelatemail

3

さらに別の試み、必要な選択を行うために?Filterとカスタム関数を使用してこの時間:

sum(sapply(Filter(function(x) x$category=="internal", mylist), `[[`, "cost")) 
#[1] 6 
0

purrrパッケージには、リストを操作するためのいくつかの素晴らしいユーティリティを持っています。ここで、keepは、リストの要素を維持するかどうか、ブールを返す述語関数を指定することができます:

library(purrr) 

mylist %>% keep(~.x[['category']] == 'internal') %>% 
    # now select the `cost` element of each, and simplify to numeric 
    map_dbl('cost') %>% 
    sum() 
## [1] 6 

~.xと述語構造は

function(x){x[['category']] == 'internal'} 
1

に速記同等である私はあなたに近づい質問rlistパッケージで。この方法は、purrrパッケージメソッド@ alistaireと同様です。

library(rlist); library(dplyr) 

mylist %>% 
    list.filter(category=="internal") %>% 
    list.mapv(cost) %>% sum() 
    # list.mapv returns each member of a list by an expression to a vector. 
関連する問題