【问题标题】:Extract certain columns from data frame R从数据框 R 中提取某些列
【发布时间】:2022-01-13 10:47:30
【问题描述】:

我的数据框如下所示:

   x s1   s2 s3  s4
1 x1  1 1954  1 yes
2 x2  2 1955  1  no
3 x3  1 1976  2 yes
4 x4  2 1954  2 yes
5 x5  3 1943  1  no

样本数据:

df <- data.frame(x=c('x1','x2','x3','x4','x5'),
                    s1=c(1,2,1,2,3),
                    s2=c(1954,1955,1976,1954,1943), 
                    s3=c(1,1,2,2,1),
                    s4=c('yes','no','yes','yes','no'))```

是否可以提取包含整数13 的数据框列?例如,新的数据框如下所示:

 newdf
   x s1 s3
1 x1  1  1
2 x2  2  1
3 x3  1  2
4 x4  2  2
5 x5  3  1

是否可以根据列中的值是否为 1 将 s1s3 列更改为 0 或 1?更改后的数据框将如下所示:

newdf2   
 x s1 s3
1 x1  1  1
2 x2  0  1
3 x3  1  0
4 x4  0  0
5 x5  0  1

【问题讨论】:

  • 您说您要提取包含 1 到 3 之间整数的列,但随后您保留了包含字符串数据的 x 变量——您想要一个不同的规则吗? (或者x 变量只是您想要保留的特殊变量?)
  • x 变量只是我想保留的一个特殊变量!

标签: r dataframe sapply


【解决方案1】:

我认为这是你所期望的:

my_df <- data.frame(x=c('x1','x2','x3','x4','x5'),
             s1=c(1,2,1,2,3),
             s2=c(1954,1955,1976,1954,1943), 
             s3=c(1,1,2,2,1),
             s4=c('yes','no','yes','yes','no'))

my_df$end <- apply(my_df, 2, function(x) paste(x, collapse = " "))
my_df <- my_df %>% group_by(x) %>% mutate(end2 = paste(str_extract_all(string = end, pattern = "1|2|3", simplify = TRUE), collapse = " "))
my_var <- which(my_df$end == my_df$end2)
my_df[, my_var] <- t(apply(my_df[, my_var], 1, function(x) ifelse(test = x == 1, yes = 1, no = 0)))
my_df <- my_df[, c(1, my_var)]

【讨论】:

    【解决方案2】:

    基础 R

    newdf <- df[, unique(c("x", names(which(sapply(df, function(z) is.numeric(z) & any(c(1, 3) %in% z)))))), drop = FALSE]
    newdf
    #    x s1 s3
    # 1 x1  1  1
    # 2 x2  2  1
    # 3 x3  1  2
    # 4 x4  2  2
    # 5 x5  3  1
    
    newdf[-1] <- lapply(newdf[-1], function(z) +(z == 1))
    newdf
    #    x s1 s3
    # 1 x1  1  1
    # 2 x2  0  1
    # 3 x3  1  0
    # 4 x4  0  0
    # 5 x5  0  1
    

    演练:

    • 首先,我们确定哪些列是数字并包含数字 1 或 3:

      sapply(df, function(z) is.numeric(z) & any(c(1, 3) %in% z))
      #     x    s1    s2    s3    s4 
      # FALSE  TRUE FALSE  TRUE FALSE 
      

      这将排除任何非数字列,这意味着包含文字 "1""3"character 列将保留。这是我的完整推断;如果您想接受字符串版本,请删除 is.numeric(z) 组件。

    • 其次,我们提取那些真实的名字,并在前面加上"x"

      c("x", names(which(sapply(df, function(z) is.numeric(z) & any(c(1, 3) %in% z)))))
      # [1] "x"  "s1" "s3"
      
    • 如果由于某种原因,"x" 也是数字并包含 1 或 3,则将其包装在 unique(.) 中(此步骤纯粹是防御性的,您可能并不严格需要它)

    • 选择那些列,防御性地添加drop=FALSE,这样如果只有一列匹配,它仍然返回完整的data.frame

    • 仅用 0 或 1 替换那些列(不包括第一列 "x"); z == 1 返回 logical,包装 +(..) 将逻辑转换为 0 (false) 或 1 (true)。

    dplyr

    library(dplyr)
    df %>%
      select(x, where(~ is.numeric(.) & any(c(1, 3) %in% .))) %>%
      mutate(across(-x, ~ +(. == 1)))
    #    x s1 s3
    # 1 x1  1  1
    # 2 x2  0  1
    # 3 x3  1  0
    # 4 x4  0  0
    # 5 x5  0  1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多