将列的字符串放在R中的另一列中

amrnrhlw  于 2023-01-10  发布在  其他
关注(0)|答案(2)|浏览(145)

我有一个df列表,下面是一个df的例子:

`Basics Chest` Anatomie                                Atlas                   
   <lgl>          <chr>                                   <chr>                   
 1 NA             NA                                      Xray                    
 2 NA             NA                                      CT                      
 3 NA             NA                                      PET-CT                  
 4 NA             CT Protokolle Chest Standard            NA

现在我想把第一列的标题--在本例中是“Basics Chest”--放在后面几列的字符串之后,如下所示:

`Basics Chest` Anatomie                                    Atlas                   
   <lgl>          <chr>                                       <chr>                   
 1 NA             NA                                          Xray - Basics Chest                   
 2 NA             NA                                          CT - Basics Chest                      
 3 NA             NA                                          PET-CT - Basics Chest                 
 4 NA             CT Protokolle Chest Standard - Basics Chest NA

正如您所看到的,NA不应该被这种情况影响(必须保留它们,所以在前面的步骤中没有过滤掉它们)。
这应该适用于所有列数可变的df列表,因为我正在考虑将其包含到for循环中。
此致

nukf8bse

nukf8bse1#

如果我正确理解了您要做的事情,我认为您要查找的是purrr库,它是tidyverse的一部分,特别是map()函数家族,这是了解您是否正在使用R的最佳工具之一;它极大地清理了代码,一旦你习惯了它,它就会变得非常有意义。2然而,它确实需要一段时间来让你理解它。3它要求你相当好地理解列表和函数。4然而,使用purrr的回报是巨大的。
map函数遍历列表或向量,并对每个元素应用一个函数。我想在R for Data Science中有整整一章都是关于它们的,这是免费的,强烈推荐。
这里需要注意的一件重要事情(您将在下面的第二步中看到)是, Dataframe 本质上是一个长度相同的向量列表。
在下面的解决方案中:

  1. I首先生成伪数据( Dataframe 列表)。
    1.编写一个函数,获取第一列的名称,然后将该文本添加到 Dataframe 中的每一列。
    1.将步骤2中创建的函数应用于整个数据框列表。
    如果你有任何问题或者我误解了什么,请告诉我。
#STEP 1: Create dummy data
df.list <- list (
  "first" = tibble(
    `name 1` = NA,
    a = c(letters[1:5], NA),
    b = c(LETTERS[1:4], NA, "HI!!")
  ),
  "second" = tibble(
    `name 2` = NA,
    d = c(letters[1:5], NA),
    e = c(LETTERS[1:4], NA, "HI!!")
  ),
  "third" = tibble(
    `name 3` = NA,
    f = c(letters[1:5], NA),
    g = c(LETTERS[1:4], NA, "HI!!")
  )
)

#STEP 2: Create function that will be applied to each data frame
add_first_col_name <- function (df) {

  
  first.name <- names(df)[1]
  
  #Note: the code below attaches the text to every column. This will turn any
  #non-text columns into text. Based on your example, I think this is okay
  #but let me know if not - there are extra steps that could solve this.
  
  df %>%
    map_df(~str_c(.x, " - ", first.name))
}

#STEP 3: Use map() to apply function to each data frame in the list
map(df.list, add_first_col_name)
2q5ifsrm

2q5ifsrm2#

我们可以在Atlaspaste中使用基于NAifelse

df1$Atlas <- with(df1, ifelse(is.na(`Basics Chest`) & !is.na(Atlas), 
paste(Atlas, "- Basics Chest"), Atlas))

对于多列,只需循环Atlas以外的列,然后执行相同的操作

df1[-1] <- lapply(df1[-1], \(x) ifelse(!is.na(x) & 
     is.na(df1[["Basics Chest"]]), paste(x, "- Basics Chest"), x))

或使用dplyr

library(dplyr)
library(stringr)
df1 <- df1 %>%
   mutate(across(-`Basics Chest`, 
   ~ case_when(!is.na(.x) & is.na(`Basics Chest`)
   ~ str_c(.x, ' - Basics Chest'))))
  • 输出
df1
Basics Chest                                    Anatomie                 Atlas
1           NA                                        <NA>   Xray - Basics Chest
2           NA                                        <NA>     CT - Basics Chest
3           NA                                        <NA> PET-CT - Basics Chest
4           NA CT Protokolle Chest Standard - Basics Chest                  <NA>

数据

df1 <- structure(list(`Basics Chest` = c(NA, NA, NA, NA), Anatomie = c(NA, 
NA, NA, "CT Protokolle Chest Standard"), Atlas = c("Xray", "CT", 
"PET-CT", NA)), class = "data.frame", row.names = c("1", "2", 
"3", "4"))

相关问题