web-dev-qa-db-ja.com

等しくないデータフレームをマージし、欠落している行を0で置き換えます

2つのdata.framesがあります。1つは文字のみで、もう1つは文字と値です。

df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e'))
df2 = data.frame(x=c('a', 'b', 'c'),y = c(0,1,0))
merge(df1, df2)
  x y
1 a 0
2 b 1
3 c 0 

Df1とdf2をマージしたい。文字a、b、およびcは良好にマージされ、0、1、0もありますが、dおよびeには何もありません。 0と0の条件で、マージテーブルにもdとeが必要です。したがって、df2 data.frameの行が欠落するたびに、df1テーブルに次のように0を配置する必要があります。

  x y
1 a 0
2 b 1
3 c 0
4 d 0
5 e 0
59
Lisann

マージのヘルプページをご覧ください。 allパラメーターを使用すると、さまざまなタイプのマージを指定できます。ここでは、_all = TRUE_を設定します。これにより、mergeは一致しない値に対してNAを返し、is.na()を使用して0に更新できます。

_zz <- merge(df1, df2, all = TRUE)
zz[is.na(zz)] <- 0

> zz
  x y
1 a 0
2 b 1
3 c 0
4 d 0
5 e 0
_

フォローアップの質問に対処するために何年も後に更新されました

マージしない2番目のデータテーブルの変数名を識別する必要があります。これにはsetdiff()を使用します。以下を確認してください。

_df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e', NA))
df2 = data.frame(x=c('a', 'b', 'c'),y1 = c(0,1,0), y2 = c(0,1,0))

#merge as before
df3 <- merge(df1, df2, all = TRUE)
#columns in df2 not in df1
unique_df2_names <- setdiff(names(df2), names(df1))
df3[unique_df2_names][is.na(df3[, unique_df2_names])] <- 0 
_

reprexパッケージ (v0.2.1)によって2019-01-03に作成

89
Chase

または、@ Chaseのコードの代替として、データベースのバックグラウンドを持つ最近のplyrファンです:

require(plyr)
zz<-join(df1, df2, type="left")
zz[is.na(zz)] <- 0
7
Nick Sabbe

Data.tableを使用した別の方法。

サンプルデータ

dt1 <- data.table(df1)
dt2 <- data.table(df2)
setkey(dt1,x)
setkey(dt2,x)

コード

dt2[dt1,list(y=ifelse(is.na(y),0,y))]
3
Wojciech Sobala

Chaseの回答(11年5月11日14:21に回答)を使用しましたが、特定の問題にその解決策を適用するためのコードを少し追加しました。

ユーザーごとに統合する料金のフレーム(ユーザー、ダウンロード)と合計のフレーム(ユーザー、ダウンロード)があり、対応する合計がない場合でも、すべての料金を含めたいと思いました。ただし、合計が欠落していない可能性があります。その場合、NAをゼロに置き換える行の選択は失敗します。

コードの最初の行はマージを行います。次の2行は、マージされたフレームの列名を変更します。 ifステートメントはNAをゼロに置き換えますが、NAを持つ行がある場合のみです。

# merge rates and totals, replacing absent totals by zero
graphdata <- merge(rates, totals, by=c("user"),all.x=T)
colnames(graphdata)[colnames(graphdata)=="download.x"] = "download.rate"
colnames(graphdata)[colnames(graphdata)=="download.y"] = "download.total"
if(any(is.na(graphdata$download.total))) {
    graphdata[is.na(graphdata$download.total),]$download.total <- 0
}
2
Ian E. Gorman

df1xのすべての値があると仮定すると、dplyr::left_join()を使用してマージし、次にbase::replace()またはtidyr::replace_na()を使用して置換できますNAsを0sとして:

library(tidyverse)

# dplyr only:
df_new <- 
  left_join(df1, df2, by = 'x') %>% 
  mutate(y = replace(y, is.na(y), 0))

# dplyr and tidyr:
df_new <- 
  left_join(df1, df2, by = 'x') %>% 
  mutate(y = replace_na(y, 0))

# In the sample data column `x` is a factor, which will give a warning with the join. This can be prevented by converting to a character before the join:
df_new <- 
  left_join(df1 %>% mutate(x = as.character(x)), 
            df2 %>% mutate(x = as.character(x)), 
            by = 'x') %>% 
    mutate(y = replace(y, is.na(y), 0))
1
sbha