R - 查找和组合多个字符列

R - Finding and combining multiple character columns

总之,我有点想做model.matrix()的逆过程。我从一项调查中获得了以下数据。

问题 1:从 'Cat'、'Dog' 或 'Sheep'
中选择一个 问题 2:选择一个随机数
问题 3:从 'Big' 或 'Small'

中选择一个

结果按以下方式放入数据框中:

    id   ans_1   ans_2   ans_3   num    size_1   size_2
    1    Cat     0       0       0.76   0        Small 
    2    0       Dog     0       0.44   0        Small 
    3    0       0       Sheep   0.52   Big      0     
    4    0       0       Sheep   0.52   Big      0     
    5    0       Dog     0       0.59   0        Small 
    6    Cat     0       0       0.97   0        Small 
    7    0       Dog     0       0.5    0        Small 
    8    0       Dog     0       0.19   0        Small 
    9    0       0       Sheep   0.01   Big      0     
   10    Cat     0       0       0.24   0        Small 

我想做的是将每个问题的答案合并到一个列中。在此示例中,ans_1、ans_2 和 ans_3 来自同一个问题,size_1 和 size_2 也来自同一个问题。将它们结合起来,结果如下:

   id    ans     num    size  
    1    Cat     0.76   Small        
    2    Dog     0.44   Small        
    3    Sheep   0.52   Big          
    4    Sheep   0.52   Big          
    5    Dog     0.59   Small        
    6    Cat     0.97   Small        
    7    Dog     0.5    Small        
    8    Dog     0.19   Small       
    9    Sheep   0.01   Big         
   10    Cat     0.24   Small        

我有多个数据集,每个数据集包含大约 100 列。这使得手工完成的工作量太大。请注意,还有像 'num' 这样的列,它们是独立存在的。同一个问题的答案总是紧挨着,就像这个例子一样。

谢谢!

数据

id = 1:10
ans_1 = c('Cat', 0, 0, 0, 0, 'Cat', 0, 0, 0, 'Cat')
ans_2 = c(0, 'Dog', 0, 0, 'Dog', 0, 'Dog', 'Dog', 0, 0)
ans_3 = c(0, 0, 'Sheep', 'Sheep', 0, 0, 0, 0, 'Sheep', 0)
num = round(runif(10),2)
size_1 = c(0, 0, 'Big', 'Big', 0, 0, 0, 0, 'Big', 0)
size_2 = c('Small', 'Small', 0, 0, 'Small', 'Small', 'Small', 'Small', 0, 
'Small')

data <- noquote(cbind(id, ans_1, ans_2, ans_3, num, size_1, size_2))

您可以使用矩阵子集和 max.col 来完成此操作。

dataNew <- data.frame(id=data$id,
                     ans=data[,2:4][cbind(seq_along(data$id), max.col(data[, 2:4] != "0"))],
                     num=data$num,
                     size=data[,6:7][cbind(seq_along(data$id), max.col(data[, 6:7] != "0"))],
                     stringsAsFactors=FALSE)

第三个变量 num 是通过对变量 2:4 进行子集化,然后使用矩阵子集化对每行中对应于所需输出的 ​​return 个元素创建的。在这种情况下,seq_along return 是一组行,max.col 用于查找每行中不为 0 的变量。

数据

data <- 
structure(list(id = 1:10, ans_1 = c("Cat", "0", "0", "0", "0", 
"Cat", "0", "0", "0", "Cat"), ans_2 = c("0", "Dog", "0", "0", 
"Dog", "0", "Dog", "Dog", "0", "0"), ans_3 = c("0", "0", "Sheep", 
"Sheep", "0", "0", "0", "0", "Sheep", "0"), num = c(0.44, 0.36, 
0.2, 0.72, 0.98, 0.94, 0.52, 0.84, 0.34, 0.04), size_1 = c("0", 
"0", "Big", "Big", "0", "0", "0", "0", "Big", "0"), size_2 = c("Small", 
"Small", "0", "0", "Small", "Small", "Small", "Small", "0", "Small"
)), .Names = c("id", "ans_1", "ans_2", "ans_3", "num", "size_1", 
"size_2"), row.names = c(NA, -10L), class = "data.frame")

您可能想使用来自 tidyr 的 unite(),然后来自 dplyr 的 mutate_if()

library(dplyr)
library(tidyr)
library(stringr)

data <- data_frame(id, ans_1, ans_2, ans_3, num, size_1, size_2)

data %>% 
    unite(ans, ans_1, ans_2, ans_3) %>% 
    unite(size, size_1, size_2) %>%
    mutate_if(is.character, str_extract, "[a-zA-Z]+")

#> # A tibble: 10 × 4
#>       id   ans   num  size
#>    <int> <chr> <dbl> <chr>
#> 1      1   Cat  0.92 Small
#> 2      2   Dog  0.79 Small
#> 3      3 Sheep  0.44   Big
#> 4      4 Sheep  0.67   Big
#> 5      5   Dog  0.00 Small
#> 6      6   Cat  0.61 Small
#> 7      7   Dog  0.67 Small
#> 8      8   Dog  0.95 Small
#> 9      9 Sheep  0.18   Big
#> 10    10   Cat  0.76 Small

如上所述,data.frame可能更合适..

ans<-apply(data[,2:4],1,function(x) x[x!="0"])
(data.new<-cbind(id=data[,1],ans,data[,5:7]))

您可以在选定字段(data[, grep('ans', colnames(data))]data[, c('ans1', 'ans2', 'ans3')])上应用函数并询问或非 0 值

ans <- apply(data[, grep('ans', colnames(data))], 1, function(x) x[x!=0])
size <- apply(data[, grep('size', colnames(data))], 1, function(x) x[x!=0])

data2 <- data.frame(id, ans, num, size)

> data2
   id   ans  num  size
1   1   Cat 0.79 Small
2   2   Dog 0.66 Small
3   3 Sheep 0.77   Big
4   4 Sheep 0.63   Big
5   5   Dog 0.48 Small
6   6   Cat 0.06 Small
7   7   Dog 0.63 Small
8   8   Dog 0.59 Small
9   9 Sheep 0.24   Big
10 10   Cat 0.96 Small