🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
R

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

Q&A

解決済

3回答

6041閲覧

R 複数の列に対してmutate(x=if_else(is.na(x1),0,1))をしたい場合

kou_irohas

総合スコア4

R

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

0グッド

0クリップ

投稿2019/11/28 07:32

編集2019/12/03 02:24

前提

R
dplyrパッケージ使用

実現したいこと

複数列に対してNAでないか否かで0,1の変数に変換したい。

変換したい変数

商品購入_1 : numeric型 #1~5000の値をとる

dataframeのイメージ

ID 商品購入_1 商品購入_2 ・・・ 商品購入_50 0001 2380 NA 2400 0002 1280 1980 980 0003 NA 2600 2480 ・ ・ ・ 9999 4980 180 ・・・ NA

変換後のdataframeのイメージ

ID 商品購入_1 商品購入_2 ・・・ 商品購入_50 0001 1 0 1 0002 1 1 1 0003 0 1 1 ・ ・ ・ 9999 1 1 ・・・ 0

一つの列に対してなら、

df %>% mutate(商品購入_1 = if_else(is.na(商品購入_1),0,1))

とすればよいが、

列が商品購入_1 ~ 商品購入_50まである場合に

df %>% mutate(商品購入_1 = if_else(is.na(商品購入_1),0,1), 商品購入_2 = if_else(is.na(商品購入_2),0,1), . . . 商品購入_50 = if_else(is.na(商品購入_50),0,1) )

とする以外の解決策がわからず、
mutate_at(vars(matches("商品購入")),funs(・・・))
みたいな感じでかけるといいなと思ったのだが、funsの中身をどうすればよいかわからず、
調べても解決策がわからなかった。

補足情報

R version 3.6.0

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

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

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

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

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

shimiken

2019/11/28 07:59

for文を使ってみてはどうでしょうか
kou_irohas

2019/12/03 02:18

データ数が大きいため(2万行くらい?)Rでfor文を回すとかなり時間がかかると思うのですがどうでしょう、、、
guest

回答3

0

自己解決

r

1df %>% 2 mutate_at(vars(starts_with("商品購入")),funs(if_else(is.na(.),0,.))) %>% 3 mutate_at(vars(starts_with("商品購入")),funs(if_else(. > 0, 1, 0))) %>% 4 mutate_at(vars(starts_with("商品購入")),funs(as.factor))

こんな感じで解決できました。
これがベストかはわかりませんが自分的には一番わかりやすかったです。
回答してくれた方ありがとうございました。

このやり方に対する意見もあったらいただきたいです。

投稿2019/12/04 05:07

kou_irohas

総合スコア4

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

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

0

単純にこんな感じでいけませんか?

R

1a <- matrix(rep(c(10, 20, 30, 40, 50, NA),8),4,12) 2a 3b <- ifelse(is.na(a), 0, 1) 4b

データフレームをマトリックスに変換しとかないとダメかもです。

投稿2019/12/03 07:44

shimiken

総合スコア368

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

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

0

一度tidyr::pivot_longer()で縦長にする
→mutateでNAの有無を示す列作る
→tidyr::pivot_wider()で元に戻す
でいかがでしょうか

library(tidyverse) #tidyr version 1.0.0 #縦長にするためのキー列を仮にnoとしています df %>% pivot_longer(-no) %>% mutate(new_value = if_else(is.na(value),0,1) %>% pivot_wider(velues_from = c(value, new_value), names_sep = "_") #出力イメージ # no | value_商品購入1 | new_value_商品購入1 | .... #--------------------------------------------------- # 1 | 1000 | 1 | .... #--------------------------------------------------- # 2 | NA | 0 | ....

投稿2019/11/28 08:24

ade-san

総合スコア15

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

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

kou_irohas

2019/12/03 02:21

今新しくdfのイメージを更新したのですが、すでにID分けされており、それが1万近くある場合にもこのやり方でいけますか?一応自分で試してまたコメントいたします。
ade-san

2019/12/03 05:38

可能だと思います。 新しいdfの書き方でしたら、ID列をキーとすると大丈夫です。 つまり、pivot_longer(-ID)とすればIDごとに商品購入1,2,3...と縦にデータ(value列)が並びます。 このvalue列に対してNAを含むかどうかをする=一括で行うということと同義になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問