如何用未知列名替换某些数据框值?

时间:2019-09-20 11:18:48

标签: r

我有一个大型数据框,其中包含未知的列名和数字值1、2、3或4。 现在,我想用其列名替换所有4个值,并用一个空值替换所有1、2和3。

当然,我可以进行某种循环,如下所示:

df <- data.frame(id=1:8,unknownvarname1=c(1:4,1:4),unknownvarname2=c(4:1,4:1))
for (i in 2:length(df)){
  df[,i] <- as.character(df[,i])
  df[,i] <- mgsub::mgsub(df[,i],c(1,2,3,4),c("","","",names(df)[i]))  
}

这将是结果:

  id unknownvarname1 unknownvarname2
1  1                 unknownvarname2
2  2                                
3  3                                
4  4 unknownvarname1                
5  5                 unknownvarname2
6  6                                
7  7                                
8  8 unknownvarname1 unknownvarname2

对于这样大小的数据帧,这根本没有问题。但是,当我在具有多达30k和多达40个未知变量的大型数据帧上尝试执行此循环时,该循环需要花一些时间才能完成。

有人知道更快的方法吗?我尝试了类似mutate()中的dplyr package之类的功能,但无法使其正常工作。

非常感谢!

6 个答案:

答案 0 :(得分:8)

使用基数R的一种方法

#Replace all the values with 1:3 with blank
df[-1][sapply(df[-1], `%in%`, 1:3)] <- ""
#Get the row/column indices where value is 4
mat <- which(df == 4, arr.ind = TRUE)
#Exclude values from first column
mat <- mat[mat[, 2] != 1, ]
#Replace remaining entries with it's corresponding column names
df[mat] <- names(df)[mat[, 2]]
df

#  id unknownvarname1 unknownvarname2
#1  1                 unknownvarname2
#2  2                                
#3  3                                
#4  4 unknownvarname1                
#5  5                 unknownvarname2
#6  6                                
#7  7                                
#8  8 unknownvarname1                

答案 1 :(得分:7)

只需使用switch给出另一个选项(尽管由于该函数未向量化,因此它需要在sapply中嵌套lapply而不会使它变得“漂亮”高效...):

基本上,switchnumeric作为switch(myNumberToTest, caseIfOne, caseIfTwo, ...)一起使用。

所以您需要的是:

df[, 2:3] <- lapply(2:3, function(x) sapply(df[, x], switch, "", "", "", names(df)[x]))

df
#  id unknownvarname1 unknownvarname2
#1  1                 unknownvarname2
#2  2                                
#3  3                                
#4  4 unknownvarname1                
#5  5                 unknownvarname2
#6  6                                
#7  7                                
#8  8 unknownvarname1                

答案 2 :(得分:7)

又一个基本的R选项,在lapply中使用ifelse(仍然在列上循环,但按列进行矢量化处理):

df <- data.frame(id=1:8,unknownvarname1=c(1:4,1:4),unknownvarname2=c(4:1,4:1))
df[,2:3] <- lapply(2:3, function(x) { ifelse(df[,x] < 4, "", colnames(df)[x]) })

给予

  id unknownvarname1 unknownvarname2
1  1                 unknownvarname2
2  2                                
3  3                                
4  4 unknownvarname1                
5  5                 unknownvarname2
6  6                                
7  7                                
8  8 unknownvarname1         

答案 3 :(得分:6)

使用WHERE xColumn NOT LIKE 'AB-C%'的另一个基数R可能性:

SQLCMD

给出:

sweep

这可以简化为:

idx <- df[, -1] == 4
sw <- sweep(idx, 2, 1:2, FUN = '*') + 1
df[, -1] <- c("", colnames(df[, -1]))[sw]

答案 4 :(得分:5)

效率较低的tidyverse选项。这是低效的,因为我们需要稍后手动选择列:

to_use <- names(df)[-1]
df %>% 
  mutate_at(vars(contains("unknown")),list(~ifelse(.==4,
                                             NA,
                                             ""))) -> new_df

new_df[-1] <-map2(new_df[-1], to_use,function(x,y) replace(x,is.na(x),y))

一种较不人工的方法,也具有不明确的缺点:

 df %>% 
   map2(.,names(.), function(x, y) ifelse( x==4, y,"")) %>% 
   as.data.frame() %>% 
   mutate(id=row.names(.)) # might be a way around  with `.id`
  id unknownvarname1 unknownvarname2
1  1                 unknownvarname2
2  2                                
3  3                                
4  4 unknownvarname1                
5  5                 unknownvarname2
6  6                                
7  7                                
8  8 unknownvarname1 

方法1的结果

new_df
     id unknownvarname1 unknownvarname2
    1  1                 unknownvarname2
    2  2                                
    3  3                                
    4  4 unknownvarname1                
    5  5                 unknownvarname2
    6  6                                
    7  7                                
    8  8 unknownvarname1 

答案 5 :(得分:5)

另一个使用B排列名称和值的选项:

col