根据另一个数据框中的值创建新的数据框。

5

数据框的外观如下:

id pom.1 pom.2 pom.3 pom.4 pom.5 pom.6 pom.7 pom.8
20764422   1   3  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>
08049335   4   2   1   5   8   7   9   3
07668511   5   2   7  <NA>  <NA>  <NA>  <NA>  <NA>
20058102   7   4   2  <NA>  <NA>  <NA>  <NA>  <NA>
17318802   6   3   5   1   9   8   2  <NA>

这是一个包含10个可能值的数据帧列表。

我需要创建另一个数据帧,该数据帧将有10列,每列对应一个列表中的值,并匹配原始数据帧。

新的数据帧应该长这样:

id c1 c2 c3 c4 c5 c6 c7 c8 c9 c10
20764422 y n y n n n n n n n
08049335 y y y y y n y y y n
07668511 n y n n y n y n n n
20058102 n y n y n n y n n n
17318802 y y y n y y n y y n

每行(c1-c10)都应该与值列表中的一个值匹配。每个id的“y”和“n”表示原始数据框中是否存在某个值。

希望这个解释足够清楚,让您明白需要做什么。

在发帖之前,我尝试了寻找答案,但要么没有答案,要么我的搜索不够好。如果已经有答案,请原谅我的冒犯。

提前致谢!


尝试使用ifelse(is.na(你的数据框名),'n','y') - Patrick Roocks
Patrick,感谢您的快速回复,但我认为您没有理解我的问题(或者我的解释不够清楚)。原始数据框中有8列,可以有1-10的值。我想创建一个新的数据框,有10个列(每个值1-10一个列),并根据原始数据框中是否有该值来放置“y”或“n”。 - Branko
1
请更清楚地解释何时应将 y 分配给某个 c 列。目前的描述并不清楚预期输出应该如何推导出来。例如,您应该指定10个可能值的列表。 - Jaap
Jaap,我希望我的上一条评论更清楚地解释了我想要的内容。 - Branko
好的,现在我明白你想要获取每行数字1到10的出现次数了。请看下面的答案。顺便说一句:如果有一个更小的例子会让问题更容易理解。 - Patrick Roocks
@AnandaMahto,你的答案非常好用。谢谢! - Branko
4个回答

6
如果您可以接受二进制的 1 和 0 而不是 "y" 和 "n",您可以尝试以下内容。
最好提供可重现的 (dput) 数据,以便我们知道您处理的是数字、字符还是因子变量。
library(data.table)
dcast(melt(as.data.table(mydf), "id"), id ~ value)
# Aggregate function missing, defaulting to 'length'
#          id 1 2 3 4 5 6 7 8 9 NA
# 1:  7668511 0 1 0 0 1 0 1 0 0  5
# 2:  8049335 1 1 1 1 1 0 1 1 1  0
# 3: 17318802 1 1 1 0 1 1 0 1 1  1
# 4: 20058102 0 1 0 1 0 0 1 0 0  5
# 5: 20764422 1 0 1 0 0 0 0 0 0  6

如果你真的想要,你可以做这样的事情:
dcast(melt(as.data.table(mydf), "id", na.rm = TRUE)[          ## melt and remove NA
      , value := factor(value, 1:10)],                        ## factor value column 
      id ~ value,                                             ## pivot value by id
      fun.aggregate = function(x) ifelse(is.na(x), "n", "y"), ## get your "y" and "n"
      fill = "n", drop = FALSE)                               ## don't drop missing factors

这将产生:

##          id 1 2 3 4 5 6 7 8 9 10
## 1: 07668511 n y n n y n y n n  n
## 2: 08049335 y y y y y n y y y  n
## 3: 17318802 y y y n y y n y y  n
## 4: 20058102 n y n y n n y n n  n
## 5: 20764422 y n y n n n n n n  n

更新

这里有一个使用tabulatechartr的“娱乐”答案:

temp <- `rownames<-`(t(apply(mydf[-1], 1, function(x) tabulate(x, nbins = 10))), mydf[[1]])
temp[] <- chartr("01", "ny", temp)
temp
#          [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# 20764422 "y"  "n"  "y"  "n"  "n"  "n"  "n"  "n"  "n"  "n"  
# 08049335 "y"  "y"  "y"  "y"  "y"  "n"  "y"  "y"  "y"  "n"  
# 07668511 "n"  "y"  "n"  "n"  "y"  "n"  "y"  "n"  "n"  "n"  
# 20058102 "n"  "y"  "n"  "y"  "n"  "n"  "y"  "n"  "n"  "n"  
# 17318802 "y"  "y"  "y"  "n"  "y"  "y"  "n"  "y"  "y"  "n" 

本答案使用的样本数据(不一定与您的相同):

mydf <- structure(list(id = c("20764422", "08049335", "07668511", "20058102", 
    "17318802"), pom.1 = c(1L, 4L, 5L, 7L, 6L), pom.2 = c(3L, 2L, 
    2L, 4L, 3L), pom.3 = c(NA, 1L, 7L, 2L, 5L), pom.4 = c(NA, 5L, 
    NA, NA, 1L), pom.5 = c(NA, 8L, NA, NA, 9L), pom.6 = c(NA, 7L, 
    NA, NA, 8L), pom.7 = c(NA, 9L, NA, NA, 2L), pom.8 = c(NA, 3L, 
    NA, NA, NA)), .Names = c("id", "pom.1", "pom.2", "pom.3", "pom.4", 
    "pom.5", "pom.6", "pom.7", "pom.8"), row.names = c(NA, 5L), class = "data.frame")

2

如果由于某些原因您不想使用任何包并想坚持使用基本的data.frame,那么您可以这样做:

# Creating some data that looks like yours
> df <- data.frame(matrix(c(101:105,sample(c(1:10,NA),40,replace=T)),5,9,dimnames=list(x=NULL,y=c("id",sapply(1:8,function(x) paste("pom",x))))))
> print(df)
   id pom.1 pom.2 pom.3 pom.4 pom.5 pom.6 pom.7 pom.8
1 101     2    NA     7    NA     5     1    NA     2
2 102     7     4     8     2     1     5    NA     4
3 103     6     8     5     2     9     8     2     7
4 104     9    NA     4     5     3     9     7     9
5 105     1     7     6     2     3     4     5     5
# Creating the output
> ndf <- t(apply(df,1,function(l) sapply(1:10,function(x) ifelse(x %in% l, 'y', 'n'))))
> dimnames(ndf) <- list(as.character(101:105),as.character(1:10))
> print(ndf)
    1   2   3   4   5   6   7   8   9   10
101 "y" "y" "n" "n" "y" "n" "y" "n" "n" "n"
102 "y" "y" "n" "y" "y" "n" "y" "y" "n" "n"
103 "n" "y" "n" "n" "y" "y" "y" "y" "y" "n"
104 "n" "n" "y" "y" "y" "n" "y" "n" "y" "n"
105 "y" "y" "y" "y" "y" "y" "y" "n" "n" "n"

请注意,我不建议在处理大型数据集时使用此解决方案。@Ananda Mahto的解决方案可能是最优的。

1
我们可以使用mtabulate
library(qdapTools)
cbind(dfN[1], mtabulate(as.data.frame(t(dfN[-1]))))

或者使用来自基本R的“table”。我们对数据集的列进行了 “unlist” 操作,除了“id”列之外,获取了“id”列(复制以使长度相同)和“unlist”列的“table”,将逻辑索引更改为数字,并用“n”、“y”替换值并与“id”列一起使用“cbind”。
tbl <- !!table(dfN$id[row(dfN[-1])], factor(unlist(dfN[-1]), levels=1:10))
tbl[] <- c('n', 'y')[tbl+1L]
`row.names<-`(cbind(dfN[1], as.data.frame.matrix(tbl)), NULL)
#         id 1 2 3 4 5 6 7 8 9 10
#1 20764422 n y n n y n y n n  n
#2  8049335 y y y y y n y y y  n
#3  7668511 y y y n y y n y y  n
#4 20058102 n y n y n n y n n  n
#5 17318802 y n y n n n n n n  n

1

使用 R 基础语法可以采用 apply 函数来处理矩阵(下面是一个较小的例子):

df <- data.frame(col1 = c(1, NA, 3), col2 = c(2, 10, NA))

as.data.frame(ifelse(t(apply(df, 1, function(x) (1:10) %in% x[!is.na(x)])), 
                     'y', 'n'))

  V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1  y  y  n  n  n  n  n  n  n   n
2  n  n  n  n  n  n  n  n  n   y
3  n  n  y  n  n  n  n  n  n   n

您可能最终需要调整行名和列名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接