質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

Q&A

解決済

2回答

801閲覧

R 欠損値のあるデータフレームの累積の計算方法

Mayu___

総合スコア4

R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

0グッド

0クリップ

投稿2021/11/05 22:33

前提・実現したいこと

使用するデータ(df)および現在の状態は以下の通りです。
t年のcumsum_priceはt-2年とt-1年とt年のpriceの合計です。
例えば2001年A社の場合、cumsum_price=200+202+199=601となります。
現状では過去3年に2002年を含まない年(2005,2006年)のcumsum_priceもNAと表示されています。

name year price cumsum_price
A社 1999 200
A社 2000 202
A社 2001 199 601
A社 2002 NA NA
A社 2003 207 NA
A社 2004 201 NA
A社 2005 201 NA
A社 2006 201 NA
B社 1999 ... ...
B社 2000 ... ...
B社 2001 ... ...

目標は以下のように、過去3年のうち1年もNAのpriceを含まない場合、数値として合計が表示されるようにしたいです。

name year price cumsum_price
A社 1999 200
A社 2000 202
A社 2001 199 601
A社 2002 NA NA
A社 2003 207 NA
A社 2003 201 NA
A社 2003 201 609
A社 2003 201 603
B社 1999 ... ...
B社 2000 ... ...
B社 2001 ... ...

実行したソースコード

"cumsum_price"を作成する際に実行したコードは以下の通りです。

do.call(rbind, c( lapply(split(df, df$name), function(x) { data.frame(x, cumsum_price = { i = findInterval(x$year-3, x$year) w = which(as.logical(i)) cs = cumsum(x$price) i[w] = cs[i[w]] cs - i })}), make.row.names=F))

ご回答をいただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

以下の通りになります。

r

1# データフレーム 2df <- data.frame( 3 "name" = c(rep("A社", 8), rep("B社", 3)), 4 "year" = c(1999:2006, 1999:2001), 5 "price_t" = c(200, 202, 199, NA, 207, 201, 201, 201, 202, 203, 201) 6) 7 8# cumsum_price 列を計算_ 9df["cumsum_price"] = apply(df, 1, function(r) { 10 y <- as.integer(r["year"]) 11 sum(df[(df$name == r["name"])&(df$year %in% (y-2):y), "price_t"][1:3]) 12}) 13 14# 表示 15print(df) 16# 17 name year price_t cumsum_price 181 A社 1999 200 NA 192 A社 2000 202 NA 203 A社 2001 199 601 214 A社 2002 NA NA 225 A社 2003 207 NA 236 A社 2004 201 NA 247 A社 2005 201 609 258 A社 2006 201 603 269 B社 1999 202 NA 2710 B社 2000 203 NA 2811 B社 2001 201 606

※ ベクタに NA が含まれている場合、sumNA を返します(sum(1, 2, NA) => NA)。また、y <- as.integer(r["year"]) としているのは apply 関数がデータフレームを一旦 matrix に変換してしまうからです(要素を character 型(string)に変換)。

投稿2021/11/06 04:45

編集2021/11/06 22:22
melian

総合スコア20655

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Mayu___

2021/11/06 21:26

ご回答ありがとうございます。 仰る通り、過去3年度分の price_t が全て揃っていて、NA を含まない場合のみ総和を出力したいです。 このケースについても教えていただけると嬉しいです。 よろしくお願いいたします。
Mayu___

2021/11/06 22:54

ご回答ありがとうございます! 質問欄で提示したデータでは上手くいったのですが、他のデータ(サンプル数、変数がさらに多いものになります)を使用して同じことを試みた結果、コード8行目について「 (y - 2):y でエラー: 引数が NA/NaN です」というエラーメッセージが表示されている状況です。 もし何か原因に心当たりがありましたら、教えていただけると大変助かります
melian

2021/11/06 23:48 編集

こちらで試してみましたが、考えられる原因としては year 列に NA か NaN が含まれている場合にそのエラーが発生します。そちらのデータを確認していただけますか?
Mayu___

2021/11/07 23:37

ご回答いただきありがとうございます! 仰る通り何らかの不具合でyear列にNAが紛れており、そこを修正した結果上手くいきました 大変助かりました
guest

0

このような回りくどい処理がほんとうに必要なんでしょうか?
もうちょっと直接的・直感的な処理を試みてはどうでしょうか。

df <- read.table(text=" name year price A社 1999 200 A社 2000 202 A社 2001 199 A社 2002 NA A社 2003 207 A社 2004 201 A社 2005 201 A社 2006 201 B社 1999 202 B社 2000 203 B社 2001 201", header=T, stringsAsFactors=F) cumsum_price <- function(name, year){ price <- 0 for(i in 0:2){ p <- df[df$name==name & df$year==year-i,"price"] if(length(p)>0){ price <- price + p }else{ price <- NA } } return(price) } df$cumsum_price <- unlist(sapply(1:nrow(df), function(x){ cumsum_price(df[x,"name"], df[x,"year"]) } ))
> df name year price cumsum_price 1 A社 1999 200 NA 2 A社 2000 202 NA 3 A社 2001 199 601 4 A社 2002 NA NA 5 A社 2003 207 NA 6 A社 2004 201 NA 7 A社 2005 201 609 8 A社 2006 201 603 9 B社 1999 202 NA 10 B社 2000 203 NA 11 B社 2001 201 606

投稿2021/11/06 00:32

KojiDoi

総合スコア13692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問