这是我数据框的一部分:
name value_1 value_2 value_3
AK x X
AK y Y
AK m M B
HU z Z
HU a A
HU f F C
KO b B
KO c C
KO d D B
我需要:
num AK HU KO
1 x z b
1 X Z B
2 y a c
2 Y A C
3 m f d
3 M F D
3 B C B
用文字表达;我对AK,HU和KO(以及许多其他人)具有价值。所有的等级都相同-因此,每个唯一ID的行数是相同的,值的数量也将是相同的。 在数据帧的这一部分中,每个人的1和2具有两个值,3具有3个值。 它实际上是强制选择任务,因此value_1:2中的值实际上仅是1和0,但我已将它们替换为a-Z以显示排序。
我尝试过:
library(reshape2)
long <- melt(df, id.vars = c("name"))
不能解决问题,因为所有内容都添加在彼此之间,而我需要根据其ID(名称)将它们重塑为长,但是随后需要将不同的名称ID放在其中彼此相邻的独立列。
感谢您的帮助。
答案 0 :(得分:0)
我必须包括一些额外的小步骤来完成此操作,因为您希望按照特定的顺序进行输出,但这应该做到:
long<-melt(df, id.vars=c("name"), value.var=c("value_1","value_2","value_3"))
long$variable<-c("11","21","31","11","21","31","11","21","31",
"12","22","32","12","22","32","12","22","32",
"13","23","33","13","23","33","13","23","33")
short<-dcast(long, variable ~ name)
final<-short[short$AK!="",]
final$variable<-round(as.numeric(final$variable)/10,0)
colnames(final)[1]<-"num"
希望这会有所帮助!
答案 1 :(得分:0)
使用以下注释中显示的输入,运行问题中显示的melt
,然后将value_1
,value_2
和value_3
转换为1、2和3并添加一个subseq
列以区分否则具有相同键的行。摆脱空的value
行,并使用dcast
删除subseq
列,将其转换回宽格式:
library(reshape2)
long <- melt(DF, id.var = "name") # from question
long2 <- transform(long, num = gsub("\\D", "", variable),
subseq = ave(1:nrow(m), name, variable, FUN = seq_along),
variable = NULL)
long3 <- subset(long2, value != "")
wide <- dcast(subseq + num ~ name, data = long3, value.var = "value")[-1]
给予:
> wide
num AK HU KO
1 1 x z b
2 2 X Z B
3 1 y a c
4 2 Y A C
5 1 m f d
6 2 M F D
7 3 B C B
根据预期进行检查:
identical(wide, expected)
## [1] TRUE
可重复输入的形式是:
Lines <- "
name value_1 value_2 value_3
AK x X
AK y Y
AK m M B
HU z Z
HU a A
HU f F C
KO b B
KO c C
KO d D B"
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE, fill = TRUE, strip.white = TRUE)
我们假设num
是一个因素,而其他数据是字符-由于问题中输入的输入方式不是可重复的,因此我们无法确定预期的目的。
expected <- structure(list(num = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 3L), .Label =
c("1", "2", "3"), class = "factor"), AK = c("x",
"X", "y", "Y", "m", "M", "B"), HU = c("z", "Z", "a", "A", "f",
"F", "C"), KO = c("b", "B", "c", "C", "d", "D", "B")), row.names = c(NA,
-7L), class = "data.frame")
此变体使用0/1数据和整数num
:
set.seed(123)
# test data
DF2 <- data.frame(name = DF$name,
value_1 = rbinom(9, 1, .5),
value_2 = rbinom(9, 1, .5),
value_3 = ifelse(DF[, 4] == "", NA, rbinom(9, 1, .5)))
long <- melt(DF2, id.var = "name")
long2 <- subset(long, !is.na(value))
long3 <- transform(long2, num = as.integer(gsub("\\D", "", variable)),
subseq = ave(1:nrow(long2), name, variable, FUN = seq_along),
variable = NULL)
wide <- dcast(subseq + num ~ name, data = long3, value.var = "value")[-1]
给予:
> wide
num AK HU KO
1 1 0 1 1
2 2 0 1 1
3 3 1 1 1
4 1 1 1 1
5 2 1 1 0
6 1 0 0 1
7 2 0 0 0
答案 2 :(得分:0)
这将提供所需的输出:
library(tidyverse)
df0=df%>%mutate(Value12=map2(value_1,value_2,c))%>%
mutate(Value=map2(Value12,value_3,c))%>%
select(name,Value)%>%
unnest()%>%
drop_na()%>%
group_by(name)%>%
mutate(i = row_number())%>%
spread(name,Value)%>%
select(-i)
df0$num=cumsum(c(toupper(df0$AK)==toupper(lag(df0$AK)),F)%>%na.omit())
> df0
# A tibble: 7 x 4
AK HU KO num
<chr> <chr> <chr> <int>
1 x z b 1
2 X Z B 1
3 y a c 2
4 Y A C 2
5 m f d 3
6 M F D 3
7 B C B 3
但是,您需要澄清填充列num的逻辑。我必须为列AK假定相同的字母(不区分大小写)具有相同的数字。
答案 3 :(得分:0)
或者,这是一个使用data.table包中的melt()
和dcast()
的解决方案。 rowid(name)
用于分别为每个name
创建行号。
它复制了预期的结果,包括列num
。
library(data.table)
long <- melt(setDT(df)[, num := rowid(name)], id.vars = c("num", "name"))[value != ""]
dcast(long, num + rowid(name) ~ name, value.var = "value")[, name := NULL][]
num AK HU KO 1: 1 x z b 2: 1 X Z B 3: 2 y a c 4: 2 Y A C 5: 3 m f d 6: 3 M F D 7: 3 B C B
library(data.table)
df <- fread("
name value_1 value_2 value_3
AK x X
AK y Y
AK m M B
HU z Z
HU a A
HU f F C
KO b B
KO c C
KO d D B", fill = TRUE)