我有一个巨大的表,其行中有未排列的数据(相对于列的名称)。该表看起来像这样:
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
答案 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
或包含该数据帧的任何变量。
告诉我它是否有效!