Замена значений в столбце, где есть совпадение - PullRequest
0 голосов
/ 13 декабря 2018

Я новичок в программировании на R и застрял на следующем примере.

В основном у меня есть два набора данных:

набор данных1:

ID       Category        
1        CatZZ         
2        CatVV         
3        CatAA  
4        CatQQ

набор данных2:

ID  Category  
1   Cat600  
3   Cat611 

Я пытаюсь перезаписать значения 'category' в наборе данных1 значениями 'category' в наборе данных2, где между двумя наборами данных есть совпадение идентификаторов.

Таким образом, результат будет выглядеть примерно так:

dataset1:

ID  Category    
1   Cat600  
2   CatVV  
3   Cat611  
4   CatQQ  

Ответы [ 5 ]

0 голосов
/ 14 декабря 2018

Вы можете сложить df2 поверх df1 и сохранить первый экземпляр для каждого ID.

с tidyverse, который будет:

library(tidyverse)
bind_rows(df2,df1) %>%
  group_by(ID) %>%
  slice(1) %>%
  ungroup()

# # A tibble: 4 x 2
#      ID Category
#   <int>    <chr>
# 1     1   Cat600
# 2     2    CatVV
# 3     3   Cat611
# 4     4    CatQQ

Или базовая версия (которая переупорядочивает строки):

subset(rbind(df2,df1), !duplicated(ID))
#   ID Category
# 1  1   Cat600
# 2  3   Cat611
# 4  2    CatVV
# 6  4    CatQQ
0 голосов
/ 13 декабря 2018

A base R подход, который использует match

df1$Category[match(df2$ID, df1$ID)] <- df2$Category
df1
#  ID Category
#1  1   Cat600
#2  2    CatVV
#3  3   Cat611
#4  4    CatQQ

data

df1 <- structure(list(ID = 1:4, Category = c("CatZZ", "CatVV", "CatAA", 
"CatQQ")), .Names = c("ID", "Category"), class = "data.frame", row.names = c(NA, 
-4L))

df2 <- structure(list(ID = c(1L, 3L), Category = c("Cat600", "Cat611"
)), .Names = c("ID", "Category"), class = "data.frame", row.names = c(NA, 
-2L))
0 голосов
/ 13 декабря 2018

Другой вариант - использовать пакет data.table.

Используя ту же настройку, что и @tmfmnk в своем ответе:

Построить пример набора данных:

df1 <- read.table(text = "ID       Category        
1        CatZZ         
2        CatVV         
3        CatAA  
4        CatQQ", header = TRUE, stringsAsFactors = FALSE)

df2 <- read.table(text = "ID  Category  
1   Cat600  
                  3   Cat611", header = TRUE, stringsAsFactors = FALSE)

Загрузить пакет data.table и преобразовать кадры данных в таблицы данных:

library(data.table)
df1 <- data.table(df1)
df2 <- data.table(df2)

Выполнить объединение влево

(взять все значения из df1, где ID совпадает с df2, и добавить туда категорию из df2, а затем создать новый столбец, объединяющий информацию из df1 и df2)

a <- df2[df1, on = "ID"][, a := ifelse(is.na(Category), i.Category, Category)]

Есть хороший вопрос и ответв соединениях data.table здесь: Соединение влево с использованием data.table

Кроме того, чтобы получить именно тот результат, о котором вы просили, вы можете сделать:

a <- df2[df1, on = "ID"][, list(ID, Category = ifelse(is.na(Category), i.Category, Category))]
0 голосов
/ 13 декабря 2018

Использование комбинации базовой функции R match и функции set таблицы данных:

matchinds = na.omit(match(dataset1$ID,dataset2$ID)) # this will give index of dataset2$ID where values of dataset1$ID were equal to values of dataset2$ID

set(x=dataset1,i=matchinds,j="Category",value=dataset2$category[matchinds])  #this will set values at matching indexes in dataset1 Category column equal to Category column matching index values in dataset2
0 голосов
/ 13 декабря 2018

В tidyverse вы можете сделать:

df1 %>%
 left_join(df2, by = c("ID" = "ID")) %>% #Merging the two dfs on ID
 mutate(Category = if_else(!is.na(Category.y), Category.y, Category.x)) %>% #If there is a match, taking the value from df2, otherwise from df1
 select(ID, Category) #Deleting the redundant variables

  ID Category
1  1   Cat600
2  2    CatVV
3  3   Cat611
4  4    CatQQ

Или:

df1 %>%
 left_join(df2, by = c("ID" = "ID")) %>% #Merging the two dfs on ID
 gather(var, val, -ID) %>% #Transforming the data from wide to long format
 arrange(ID) %>% #Arranging by ID
 group_by(ID) %>% #Grouping by ID
 mutate(Category = if_else(!is.na(nth(val, 2)), nth(val, 2), first(val))) %>% #If non-NA, taking the value from df2, otherwise from df1
 spread(var, val) %>% #Returning the data to wide format
 select(ID, Category) #Removing the redundant variables 

     ID Category
  <int> <chr>   
1     1 Cat600  
2     2 CatVV   
3     3 Cat611  
4     4 CatQQ

Пример данных:

df1 <- read.table(text = "ID       Category        
1        CatZZ         
2        CatVV         
3        CatAA  
4        CatQQ", header = TRUE, stringsAsFactors = FALSE)

df2 <- read.table(text = "ID  Category  
1   Cat600  
                  3   Cat611", header = TRUE, stringsAsFactors = FALSE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...