【问题标题】:R Tibble Tidying DilemmaR Tibble 整理困境
【发布时间】:2019-01-07 21:58:13
【问题描述】:

我正在尝试在我的 R 脚本中整理我的数据,以便我可以对整理后的数据集进行一些统计分析。

其中一列列出了对(其中 6 个),它们对应于三个单独的输出值“块”。最小可重现数据集如下。

dput(head(data, 6)) 
structure(list(pairs = c("ABC", "ACB", "BAC", "BCA", "CBA", "CAB"), block1vals = c(1, 3, 5, 7, 9, 10), block2vals = c(4, 66, 34, 66, 21, 21), block3vals = c(53, 22, 12, 65, 21, 22)), .Names = c("pairs", "block1vals", "block2vals", "block3vals"), row.names = c(NA, 6L), class = "data.frame")

我得到了我的代码来获取对,并为给定块标记每个参与者的 A/B/C 值,每个块的列;这行得通:

第 1 块:

data$block1types <- sapply(data$pairs, function(x){
  if(x == "ABC") { return("Type A")}
  if(x == "ACB") { return("Type A")}
  if(x == "BAC") { return("Type B")}
  if(x == "BCA") { return("Type B")}
  if(x == "CBA") { return("Type C")}
  if(x == "CAB") { return("Type C")}
})

第 2 块:

data$block2types <- sapply(data$pairs, function(x){
  if(x == "ABC") { return("Type B")}
  if(x == "ACB") { return("Type C")}
  if(x == "BAC") { return("Type A")}
  if(x == "BCA") { return("Type C")}
  if(x == "CBA") { return("Type B")}
  if(x == "CAB") { return("Type A")}
})

第 3 块:

data$block3types <- sapply(data$pairs, function(x){
 if(x == "ABC") { return("Type C")}
if(x == "ACB") { return("Type B")}
if(x == "BAC") { return("Type C")}
if(x == "BCA") { return("Type A")}
if(x == "CBA") { return("Type A")}
if(x == "CAB") { return("Type B")}
})

我现在要做的是重新组织数据,以便有一列包含所有“类型 A”参与者值(无论 A 位于哪个块中)以及一个用于“类型 B”和一种用于“C 型”。

所以理想的输出是:

data$TypeA <- c(1, 3, 34, 65, 21, 21)
data$TypeB <- c(4, 22, 5, 7, 21, 22)
data$TypeC <- c(53, 66, 12, 66, 9, 10)

我无法弄清楚如何做到这一点而不产生问题。我这样做的尝试是,在数据集之外创建两列,然后我希望可以传播:

BlockTypes<- combine(data$block1types, data$block2types, data$block3types, .id = NULL)     
BlockTotals<- combine(data$block1vals, data$block2vals, data$block3vals, .id = NULL) 

然后我尝试这样做:

spread(data, key= BlockTypes, value=BlockTotals, fill = 0)

这失败了:var 必须计算为单个数字或列名,而不是字符向量。不过,我确实认为,更大的问题是将列放在数据集之外。我不能对它们使用扩展函数,因为它们在数据集之外。所以我有点坚持如何做到这一点,如果组合功能不能与 tibble 一起使用。

【问题讨论】:

  • 您可以提取第一个(或第二个或第三个)字母并将其粘贴到 type 之后,而不是所有那些 if-statements,以生成所需的列。这样会更有效率。
  • 但是关于您的问题,我们需要看到一个最小的可重现数据集和该数据集上的示例所需输出。请提供reproducible example in r。我提供的链接会告诉你如何做。此外,请拨打tour 并访问how to ask。干杯。

标签: r


【解决方案1】:

如果我全神贯注,我确信有更好的方法来做到这一点,但这里有一些工作。

首先,我们使用 substr 函数为您的类型提取第一个、第二个和第三个字符。我使用粘贴功能将“类型”部分包含在我们执行的提取中。这比像你那样做每个组合要好得多。

接下来,我们检查了 3 次数据(每种类型一次)。每次我们遍历数据时,我们都会使用块类型来查看是否应该提取块值。

library(tidyverse)
data <- tibble(
pairs = c("ABC", "ACB", "BAC", "BCA", "CBA", "CAB"),
block1vals = c(1, 3, 5, 7, 9, 10),
block2vals = c(4, 66, 34, 66, 21, 21),
block3vals = c(53, 22, 12, 65, 21, 22)
)

data %>%
  mutate(
    block1types = paste0("Type ",substr(pairs, 1, 1)),
    block2types = paste0("Type ",substr(pairs, 2, 2)),
    block3types = paste0("Type ",substr(pairs, 3, 3))) %>%
  mutate(
    TypeAValues = case_when(
    block1types == "Type A" ~ block1vals,
    block2types == "Type A" ~ block2vals,
    block3types == "Type A" ~ block3vals)) %>%
  mutate(
    TypeBValues = case_when(
    block1types == "Type B" ~ block1vals,
    block2types == "Type B" ~ block2vals,
    block3types == "Type B" ~ block3vals)) %>%
  mutate(
    TypeCValues = case_when(
    block1types == "Type C" ~ block1vals,
    block2types == "Type C" ~ block2vals,
    block3types == "Type C" ~ block3vals))

【讨论】:

    【解决方案2】:

    这是一种利用 dplyrstringr 包的方法。

    library(dplyr)
    library(stringr)
    
    data %>%
      # For each letter, determine the position of that letter in the entry in the 'pairs' column
      mutate(a = str_locate(pairs, 'A')[,'start'],
             b = str_locate(pairs, 'B')[,'start'],
             c = str_locate(pairs, 'C')[,'start']) %>% 
      # Based on the letter's position, pull the value from the appropriate column
      mutate_at(.vars = vars(a, b, c),
                .funs = funs(case_when(. == 1 ~ block1vals,
                                       . == 2 ~ block2vals,
                                       . == 3 ~ block3vals)))
    

    str_locate() 的调用看起来很奇怪的原因是调用str_locate() 的输出是一个矩阵。

    函数的输出如下所示:

    pairs <- c('ABCDE')
    str_locate(pairs, 'BC')
    
         start end
    [1,]     2   3
    

    要仅返回字母“B”的位置,您需要从矩阵中提取标题为 start 的列。

    您可以通过编写以下代码将调用str_locate() 与列提取结合起来:

    str_locate(pairs, 'BC')['start']

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 2018-05-08
      • 1970-01-01
      • 2019-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多