как избежать перезаписи при объединении нескольких наборов данных в г - PullRequest
1 голос
/ 19 июня 2019

Предположим, у меня есть два набора данных df1 и df2 следующим образом:

df1 <- data.frame(Id = c(1L,2L,3L,4L,5L,6L,7L,8L), pricetag = c("na","na","na","na","na","na","na","na"),stringsAsFactors=F)
df2 <- data.frame(Id=c(1L,2L,3L,4L), price = c(10,20,30,40), stringsAsFactors=F)

> df1
  Id pricetag
1  1       na
2  2       na
3  3       na
4  4       na
5  5       na
6  6       na
7  7       na
8  8       na
> df2
  Id price
1  1    10
2  2    20
3  3    30
4  4    40 

Я пытаюсь вставить значения цены от df2 до df1, сопоставляя идентификатор с помощью этой функции.

df1$pricetag <- df2$price[match(df1$Id, df2$Id)]

, который обеспечивает это:

> df1
  Id pricetag
1  1       10
2  2       20
3  3       30
4  4       40
5  5       NA
6  6       NA
7  7       NA
8  8       NA

У меня есть третий набор данных. Я пытаюсь следовать той же процедуре.

df3 <- data.frame(Id=c(5L,6L,7L,8L), price=c(50,60,70,80),stringsAsFactors=F)
> df3
  Id price
1  5    50
2  6    60
3  7    70
4  8    80

df1$pricetag <- df3$price[match(df1$Id, df3$Id)]

> df1
  Id pricetag
1  1       NA
2  2       NA
3  3       NA
4  4       NA
5  5       50
6  6       60
7  7       70
8  8       80

Однако он перезаписывает информацию о ценах, поступающую от df2 в df1. Можно ли отключить эту опцию, когда я повторяю ту же процедуру?

Ответы [ 3 ]

2 голосов
/ 19 июня 2019

Замените

df1$pricetag <- df3$price[match(df1$Id, df3$Id)]

, если хотите выполнить update-join (перезаписать df1 данными в df3) на:

idx <- match(df1$Id, df3$Id)
idxn <- which(!is.na(idx))
df1$pricetag[idxn] <- df3$price[idx[idxn]]
rm(idx, idxn)
df1
#  Id pricetag
#1  1       10
#2  2       20
#3  3       30
#4  4       40
#5  5       50
#6  6       60
#7  7       70
#8  8       80

в случаеВы хотите сделать gap-fill-join (заполнить NA в df1 данными в df3) с помощью:

idxg <- which(is.na(df1$pricetag))
idx <- match(df1$Id[idxg], df3$Id)
idxn <- which(!is.na(idx))
df1$pricetag[idxg][idxn] <- df3$price[idx[idxn]]
rm(idxg, idx, idxn)
df1
#  Id pricetag
#1  1       10
#2  2       20
#3  3       30
#4  4       40
#5  5       50
#6  6       60
#7  7       70
#8  8       80
1 голос
/ 19 июня 2019

Вы можете использовать функцию is.na, чтобы определить строки для поиска:

w = which(is.na(df1$pricetag))
df1$pricetag[w] <- df3$price[match(df1$Id[w], df3$Id)]

  Id category pricetag
1  1       na       10
2  2       na       20
3  3       na       30
4  4       na       40
5  5       na       50
6  6       na       60
7  7       na       70
8  8       na       80

Для пакета data.table есть более удобный синтаксис:

df1 <- data.frame(Id=c(1L,2L,3L,4L,5L,6L,7L,8L), category="na", stringsAsFactors=FALSE)

library(data.table)
setDT(df1); setDT(df2); setDT(df3)

df1[, pricetag := NA_real_]
for (odf in list(df2, df3)) 
  df1[is.na(pricetag), 
    pricetag := odf[.SD, on=.(Id), x.price]
][]

   Id category pricetag
1:  1       na       10
2:  2       na       20
3:  3       na       30
4:  4       na       40
5:  5       na       50
6:  6       na       60
7:  7       na       70
8:  8       na       80

Этот вид слияния называется «объединением обновлений».

0 голосов
/ 20 июня 2019

Я сделал пакет Safejoin для этого:

# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)
library(tidyverse)

df1 %>% 
  rename(price = pricetag) %>%
  mutate_at("price", as.numeric) %>% # make regular numeric NAs from your "na" characters
  safe_left_join(df2, "Id", conflict = coalesce) %>% 
  safe_left_join(df3, "Id", conflict = coalesce)

#   Id price
# 1  1    10
# 2  2    20
# 3  3    30
# 4  4    40
# 5  5    50
# 6  6    60
# 7  7    70
# 8  8    80
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...