重新排列表中的值

时间:2018-06-13 12:41:07

标签: r unix dataframe

我有一个巨大的表,其行中有未排列的数据(相对于列的名称)。该表看起来像这样:

A  B  C
A1 B1 C1
A2 C2 NA
A3 C3 B3
NA B4 C4

我想知道是否有办法重新安排这个表,以便所有以" A"将出现在第一列以及以" B"开头的所有值将在第二栏等等......

期望的结果将是这样的:

A  B  C
A1 B1 C1
A2 NA C2
A3 B3 C3
NA B4 C4

5 个答案:

答案 0 :(得分:1)

read.table(text = "
A  B  C
A1 B1 C1
A2 C2 NA
A3 C3 B3
NA B4 C4",
header = T) -> df

dfnew <- matrix(c(paste0(rep(LETTERS[1:3], each = 4), seq(1:4))), ncol = 3, nrow = 4)
dfnew[!dfnew %in% sort(as.character(unlist(df)))] <- NA
dfnew

     [,1] [,2] [,3]
[1,] "A1" "B1" "C1"
[2,] "A2" NA   "C2"
[3,] "A3" "B3" "C3"
[4,] NA   "B4" "C4"

简而言之:创建一个包含所有可能的字母和数字组合的新矩阵,并将它们设置为NA,这些不在原始表格中。

答案 1 :(得分:1)

对于每一行,它会在df[1,]中找到每个元素的第一个字母,并将该元素移动到与library(tidyverse) df %>% pmap(~{ x <- c(...) ind <- map_dbl(substr(x, 1, 1), ~grep(.x, df[1,])[1]) %>% .[!is.na(.)] rep(NA, 3) %>% `[<-`(ind, x[!is.na(x)])}) %>% do.call(what = rbind) %>% as.data.frame # V1 V2 V3 # 1 A1 B1 C1 # 2 A2 <NA> C2 # 3 A3 B3 C3 # 4 <NA> B4 C4 中找到的匹配项相同的列。

container.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();

答案 2 :(得分:1)

以下是使用data.table

进行处理的一种有效方法
library('data.table')
setDT(df1)  # assign data table by reference
# melt df1 data with unique id for each row
df1 <- melt( data = df1[, id := .I], measure.vars = setdiff( names(df1), 'id' ))  
# assign variable = NA which has value = NA, and variable = column_names for other values
df1[, variable := gsub("[0-9]", "", value)]
# rearrange df1 into multiple columns and remove NA and id columns
dcast(df1, "id ~ variable", value.var = "value")[, `:=` (`NA` = NULL, id = NULL ) ][]

输出:

#     A  B  C
# 1: A1 B1 C1
# 2: A2 NA C2
# 3: A3 B3 C3
# 4: NA B4 C4

数据:

df1 <- read.table(text = "
           A  B  C
           A1 B1 C1
           A2 C2 NA
           A3 C3 B3
           NA B4 C4",
           header = TRUE, stringsAsFactors = FALSE) 

修改

使用上面的数据。

library('data.table')
setDT(df1)[, D:= c( NA_character_)] # add column D
df1[, id := .I] # add unique id for each row
nm <- copy( setdiff( names(df1), 'id' ) ) # get column names and remove id
df1 <- dcast( data = melt( data = df1, measure.vars = nm)[, variable := gsub("[0-9]", "", value)],
              formula = "id ~ variable", 
              # subsetting is done because, two NA values are passed to the aggregate function two times ( column D and A for row-4; column C and D for row-2 ). 
              # you can check it using this: function(x) print(x)
              fun = function(x)x[1],  
              value.var = "value",
              fill = NA_character_ )[, id := NULL ][]
# check for number of columns
if( ncol(df1) > length(nm) ){
  df1[, `NA` := NULL ] # remove extra NA column
  nm <- setdiff(names(df1), 'NA') # remove extra column name: NA
} 
# rename columns efficiently by reference
setnames( df1, nm)

<强>输出

print(df1)
#     A  B  C  D
# 1: A1 B1 C1 NA
# 2: A2 NA C2 NA
# 3: A3 B3 C3 NA
# 4: NA B4 C4 NA

答案 3 :(得分:1)

我们可以将pmatch用于apply来电,然后重新转换为具有正确名称的data.frame

abc <- names(df)
setNames(as.data.frame(t(
  apply(df,1,function(x) x[pmatch(abc,x)])
  )),abc)

#      A    B  C
# 1   A1   B1 C1
# 2   A2 <NA> C2
# 3   A3   B3 C3
# 4 <NA>   B4 C4

这就是pmatch在这里工作的方式:

x <- c("A2","C2",NA)
x[pmatch(abc,x)]
# [1] "A2" NA   "C2"

答案 4 :(得分:0)

这是一个非常糟糕的解决方案:

rm(list=ls())

dataset<-read.csv("exampleSO.csv",header = F); 

a<-as.matrix.data.frame(dataset);

loc<-as.vector(a[1,]); 

ourM<-a[2:5,]; 

x<-matrix(data=NA, nrow=4,ncol=3)

for (i in 1:nrow(ourM)){
  for(j in 1:ncol(ourM)){
    place<-which(substr(ourM[i,j],1,1)==loc)
    x[i,place] <- ourM[i,j]
  }
}

as.matrix.data.frame(rbind(loc,x))

#result 
     [,1][,2] [,3]
[1,] "A"  "B"  "C" 
[2,] "A1" "B1" "C1"
[3,] "A2" NA   "C2"
[4,] "A3" "B3" "C3"
[5,] NA   "B4" "C4"

将exampleSO.csv替换为包含数据的任何.csv或包含该数据帧的任何变量。

告诉我它是否有效!