Объединение таблиц и изменение значений одновременно в R - PullRequest
0 голосов
/ 20 мая 2019

У меня сложная проблема с кодированием, надеюсь, вы можете помочь:

Каждый месяц мне приходится вносить изменения в таблицу поиска, используя таблицу изменений, в которой указаны (1) новые продукты, которые необходимо добавить, и (2) изменения в названиях продуктов. Я пытаюсь автоматизировать этот процесс, потому что я обрабатываю более 40000 строк данных. Здесь слишком много конфиденциальных данных, чтобы показать их, но я привел небольшой пример данных и процесса ниже:

Таблица поиска

dput(LookupFile)
structure(list(ProductTag = structure(c(1L, 6L, 3L, 5L, 2L, 7L, 
4L), .Label = c("Confect", "Orange", "Pastries", "Root", "Sauces", 
"Spread", "White"), class = "factor"), Brand = structure(c(1L, 
1L, 1L, 2L, 2L, 3L, 4L), .Label = c("A", "B", "C", "D"), class = "factor"), 
    BrandID = c(340, 340, 340, 400, 400, 402, 403), Name = structure(c(3L, 
    4L, 1L, 7L, 2L, 5L, 6L), .Label = c("Cakes", "Carrots", "Choc", 
    "Honey", "Onions", "Potatoes", "Syrups"), class = "factor"), 
    NameID = c(200, 700, 100, 300, 1000, 1200, 1700)), class = "data.frame", row.names = c(NA, 
-7L))

Таблица изменений

dput(ChangesFiles)
structure(list(ProductTag = structure(c(1L, 3L, 2L), .Label = c("Breads", 
"Confect", "Flours"), class = "factor"), Brand = structure(c(1L, 
2L, 1L), .Label = c("A", "D"), class = "factor"), BrandID = c(340, 
403, 340), Name = structure(c(2L, 3L, 1L), .Label = c("Chocolate", 
"Gluten", "Staple"), class = "factor"), NameID = c(4000, 3400, 
200)), class = "data.frame", row.names = c(NA, -3L))

Я знаю, rbind позволяет мне добавлять новые данные в таблицу поиска:

rbind(LookupFile,ChangesFiles)

Однако существует дополнительный уровень необходимости вносить изменения в существующие строки (т. Е. Название продукта). В приведенном мной примере я хочу изменить следующую запись, используя запись ChangesFiles, которая заменяет Name = 'Choc' на 'Chocolate':

<ProductTag = 'Confect', Brand = 'A', BrandID = '340', Name = 'Choc', NameID = '200'

Это небольшая выборка данных, поэтому я мог легко внести это изменение вручную. Тем не менее, как бы я сделал изменения в больших масштабах?

Я бы хотел, чтобы это выглядело так:

     ProductTag Brand BrandID   Name   NameID
1     Confect     A     340 Chocolate    200
2      Spread     A     340     Honey    700
3    Pastries     A     340     Cakes    100
4      Sauces     B     400    Syrups    300
5      Orange     B     400   Carrots   1000
6       White     C     402    Onions   1200
7        Root     D     403  Potatoes   1700
8      Breads     A     340    Gluten   4000
9      Flours     D     403    Staple   3400

Ответы [ 4 ]

0 голосов
/ 20 мая 2019

data.table на помощь! Это однострочник ..

Используйте объединение обновлений для обновления только имени-столбца.

library( data.table )
setDT(LookupFile)[ setDT(ChangesFiles), Name := i.Name, on = .(ProductTag, Brand, BrandID)][]

#    ProductTag Brand BrandID      Name NameID
# 1:    Confect     A     340 Chocolate    200
# 2:     Spread     A     340     Honey    700
# 3:   Pastries     A     340     Cakes    100
# 4:     Sauces     B     400    Syrups    300
# 5:     Orange     B     400   Carrots   1000
# 6:      White     C     402    Onions   1200
# 7:       Root     D     403  Potatoes   1700

setDT() используется для преобразования ваших data.frames в data.table-class. Если ваши данные уже в data.table - классе,

LookupFile [ChangesFiles, Name: = i.Name, on =. (ProductTag, Brand, BrandID)] []

также будет работать.

0 голосов
/ 20 мая 2019

Работа с вашими данными (и просто переименование их в Changes & Lookup) в tidyverse:

library(tidyverse)

bind_rows(
  anti_join(Changes, Lookup,  by = colnames(Changes)),   # data  without changes
  anti_join(Lookup,  Changes, by = colnames(Lookup)[-4]) # changed names & added
  ) %>%
  arrange(BrandID, NameID)

#   ProductTag Brand BrandID      Name NameID
# 1   Pastries     A     340     Cakes    100
# 2    Confect     A     340 Chocolate    200
# 3     Breads     A     340    Gluten   4000
# 4     Spread     A     340     Honey    700
# 5     Orange     B     400   Carrots   1000
# 6     Sauces     B     400    Syrups    300
# 7      White     C     402    Onions   1200
# 8       Root     D     403  Potatoes   1700
# 9     Flours     D     403    Staple   3400
0 голосов
/ 20 мая 2019

С LookupFile берут только те строки, которые не определены в ChangesFiles, а с ChangesFiles берут все.

key <- c("BrandID", "NameID") #Assuming that BrandID and NameID need to be unique
rbind(LookupFile[!interaction(LookupFile[key]) %in% interaction(ChangesFiles[key]),], ChangesFiles)

   ProductTag Brand BrandID      Name NameID
2      Spread     A     340     Honey    700
3    Pastries     A     340     Cakes    100
4      Sauces     B     400    Syrups    300
5      Orange     B     400   Carrots   1000
6       White     C     402    Onions   1200
7        Root     D     403  Potatoes   1700
1      Breads     A     340    Gluten   4000
21     Flours     D     403    Staple   3400
31    Confect     A     340 Chocolate    200

Если у вас есть что-то, что вы хотите удалить, и вы пометите это какNA в ChangesFiles вы можете использовать:

rbind(LookupFile[!interaction(LookupFile[key]) %in% interaction(ChangesFiles[key]),], ChangesFiles[complete.cases(ChangesFiles),])
0 голосов
/ 20 мая 2019

Вот вариант Vlookup

> library(qdapTools)
> LookupFile$Name <- as.character(LookupFile$Name) # just for not dealing with factors
> replace <- as.character(LookupFile$ProductTag %l% ChangesFiles[,c(1,4)])  # here's a Vlookup
> ind <- !is.na(replace) # identifying value to replace
> LookupFile$Name[ind] <- replace[ind] # replacing
> rbind(LookupFile,ChangesFiles) # delivering your desired output
   ProductTag Brand BrandID      Name NameID
1     Confect     A     340 Chocolate    200
2      Spread     A     340     Honey    700
3    Pastries     A     340     Cakes    100
4      Sauces     B     400    Syrups    300
5      Orange     B     400   Carrots   1000
6       White     C     402    Onions   1200
7        Root     D     403  Potatoes   1700
8      Breads     A     340    Gluten   4000
9      Flours     D     403    Staple   3400
10    Confect     A     340 Chocolate    200
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...