繁体   English   中英

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

[英]Create new data frame based on values from another data frame

数据框看起来像这样:

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”表示原始数据帧中不存在某些值。

希望这种exlanation足以理解需要做什么。

在发布之前我试图找到答案,但要么没有答案,要么我的搜索不够好。 无论如何,对不起,如果我发布了答案已经在这里可用。

提前致谢!

如果你可以使用二进制1和0而不是“y”和“n”,你可以尝试类似下面的内容。

如果您提供可重现的( dput )或数据,以便我们知道您是在处理数字,字符还是因子变量,它会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

更新

这是使用tabulate和制chartr的“有趣”答案:

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")

如果由于某种原因你不想使用任何软件包并且想要坚持使用基本的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的解决方案可能是最优的。

我们可以使用mtabulate

library(qdapTools)
cbind(dfN[1], mtabulate(as.data.frame(t(dfN[-1]))))

或者使用base R table 我们unlist的数据集的列除了“ID”栏,让table “ID”列(复制,使长度相同)和unlist编列,更改逻辑指数数值,由“N”替换值,'y'和cbind与'id'列。

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

使用基础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

您可能最终必须调整rownames和colnames。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM