用 R 中的用户定义函数替换 Dataframe 列值

Replace Dataframe Column Values with User Defined Function in R

我在一个列中有一组值,我正试图用一个 since 值替换

col1
a
a;a;b;c
c;b;a
NA
b;b;b

我想用 mixed 或单个现值替换所有值,例如 a;a;a;a 变为 a

预期输出

col1
a
Mixed
Mixed
NA
b

代码

grouping = function(x){
y = as.list(strsplit(x, ";")[[1]])

#select first element, and test if each is the same element.
z = ""
for (i in 1:length(y)){
  if (as.character(y[1]) != as.character(y[i])) {
    z = 'mixed'
    break
  } else {
    z = as.character(y[1])
  }
}
return(z)
}

db %>%
select(col1) %>%
mutate(
test = grouping(col1)
)

我已经尝试了几种不同的方法,要么以它根本无法工作而告终,要么为所有内容提供 a 的值

我们可以从'col1'中提取字母的子串,用[=17=检查不同元素的个数],用case_when把那些有多个唯一元素的改成'Mixed'

library(dplyr)
library(stringr)
library(purrr)
df1 %>%
    mutate(col1 = case_when(map_dbl(str_extract_all(col1,
         "[a-z]"), n_distinct) >1 ~ "Mixed",
       is.na(col) ~ NA_character_, 
      TRUE ~ substr(col1, 1, 1)))

-输出

#  col1
#1     a
#2 Mixed
#3 Mixed
#4  <NA>
#5     b

或者另一种选择是用 separate_rows 分隔符拆分列,并按 row_numbersummarise 具有多行的元素进行分组(在 distinct) 为 'Mixed'

library(tidyr)
df1 %>% 
   mutate(rn = row_number()) %>%
   separate_rows(col1) %>% 
   distinct() %>%
   group_by(rn) %>% 
   summarise(col1 = case_when(n() > 1 ~ 'Mixed', TRUE ~ first(col1)), 
        .groups = 'drop') %>%
   select(-rn)

-输出

# A tibble: 5 x 1
#  col1 
#  <chr>
#1 a    
#2 Mixed
#3 Mixed
#4 <NA> 
#5 b    

或使用 base R 和紧凑选项

v1 <- gsub("([a-z])\1+", "\1", gsub(";", "", df1$col1))
replace(v1, nchar(v1) > 1, "Mixed")
#[1] "a"     "Mixed" "Mixed" NA      "b"    

OP 函数中的问题是它仅提取第一个 [[1]] list 元素

as.list(strsplit(x, ";")[[1]])

as strsplit returns a list 其中 length 等于初始数据的行数。所以,基本上只选择第一个,它被回收

数据

df1 <- structure(list(col1 = c("a", "a;a;b;c", "c;b;a", NA, "b;b;b")),
class = "data.frame", row.names = c(NA, 
-5L))

您也可以考虑将此用于您的功能并使用 base R:

#Function  
myfun <- function(x)
{
  y <- unlist(strsplit(x, ";"))
  if(length(unique(y))==1)
  {
    z <- unique(y)
  } else
  {
    z <- 'Mixed'
  }
}
#Apply
df$New <- apply(df,1,myfun)

输出:

df
     col1   New
1       a     a
2 a;a;b;c Mixed
3   c;b;a Mixed
4    <NA>  <NA>
5   b;b;b     b

使用了一些数据:

#Data
df <- structure(list(col1 = c("a", "a;a;b;c", "c;b;a", NA, "b;b;b")), class = "data.frame", row.names = c(NA, 
-5L))

通过定义用户函数的基本 R 选项f

f <- function(x) ifelse(length(u <- unique(unlist((strsplit(x, ";"))))) > 1, "Mixed", u)

这样

> transform(df, col1 = Vectorize(f)(col1))
   col1
1     a
2 Mixed
3 Mixed
4  <NA>
5     b

您可以将 grouping 函数编写为:

grouping <- function(x) {
  sapply(strsplit(x, ';'), function(x) 
        if(length(unique(x)) == 1) unique(x) else 'Mixed')
}
db$test <- grouping(db$col1)
db

#     col1  test
#1       a     a
#2 a;a;b;c Mixed
#3   c;b;a Mixed
#4    <NA>  <NA>
#5   b;b;b     b