【问题标题】:Creating a loop to add labels to colums: library(Hmisc)创建循环以将标签添加到列:库(Hmisc)
【发布时间】:2019-01-28 17:40:09
【问题描述】:

我有一个如下所示的数据集:

  Year      Country  Matchcode  P             H
1 2000      France        0001  1213          1872     
2 2001      France        0002  1234          2345      
3 2000      UK            0003  1726          2234      
4 2001      UK            0004  6433          9082  

我有另一个数据集,看起来像这样:

Indicator Code  Indicator Name
P               Power
H               Happiness

我想在第二个数据集的第二列(Power,Happiness)中添加信息作为第一个数据集中使用循环的缩写的标签,但我不知道如何编写循环。

这是我走了多远:

library(Hmisc)
for i in df2[,1]{
if (df1[,i] == df2[i,]){
label(df1[,i]) <- df2[i,2]
}}

但这只是检查名称是否相同而不搜索它。 有人可以进一步指导吗?

期望的输出:

  Year      Country  Matchcode  P(label=Power) H(label=Happiness)
1 2000      France        0001            1213              1872     
2 2001      France        0002            1234              2345      
3 2000      UK            0003            1726              2234      
4 2001      UK            0004            6433              9082  

【问题讨论】:

  • 我还是不明白你在做什么。您是否只想将label = Powerlabel = Happiness 分别添加到列名PH 中?我不明白你想用Hmisc::label 做什么。 Hmisc::label 只是设置/读取变量的label 属性。列名是普通的character 向量。
  • colnames(df[4:5])
  • @MauritsEvers 哈哈,对不起,我显然不善于解释。好吧,实际上我只想将 Power 作为标签添加到 P,Happiness 作为标签添加到 H 等等。我知道在这个例子中它没有多大意义,但它对我的实际数据集非常有用
  • @milan 谢谢你的回答。我正在寻找更通用的解决方案。实际数据集大约有 1600 个变量。
  • @TomKisters Hmisc::label(x) 为特定对象添加一个属性(您可以通过attributes(x) 进行检查)。在我看来,您想要做的就是更改某些列的列名(基于查找)。 AntoniosK 在下面的回答是否符合您的要求?

标签: r for-loop if-statement label hmisc


【解决方案1】:

这是dplyr 解决方案:

# example datasets
df = read.table(text = "
Year      Country  Matchcode  P             H
1 2000      France        0001  1213          1872     
2 2001      France        0002  1234          2345      
3 2000      UK            0003  1726          2234      
4 2001      UK            0004  6433          9082 
", header=T)

df2 = read.table(text = "
IndicatorName IndicatorCode
P    Power
H    Happiness 
", header=T)

library(dplyr)

data.frame(original_names = names(df)) %>%                     # get original names
  left_join(df2, by=c("original_names"="IndicatorName")) %>%   # join names that should be updated
  mutate(new_names = ifelse(is.na(IndicatorCode), original_names, paste0(original_names,"(label=",IndicatorCode,")"))) %>%  # if there is a match update the name
  pull(new_names) -> list_new_names                            # get column of new names and store it in a vector

# update names
names(df) = list_new_names

# check new names
df

#   Year Country Matchcode P(label=Power) H(label=Happiness)
# 1 2000  France         1           1213               1872
# 2 2001  France         2           1234               2345
# 3 2000      UK         3           1726               2234
# 4 2001      UK         4           6433               9082

【讨论】:

    【解决方案2】:

    这会奏效。使用%in%找到对应的文字,使用paste0生成标签。

    colnames(df1)[4:5] <- paste0(colnames(df1)[4:5], '(label=', df2$V2[colnames(df1)[4:5] %in% df2$V1], ')')
    
    df1
    
    Year Country Matchcode P(label=Power) H(label=Happiness)
    1 2000  France         1           1213               1872
    2 2001  France         2           1234               2345
    3 2000      UK         3           1726               2234
    4 2001      UK         4           6433               9082
    

    使用的数据

    df1 <- read.table(text="Year      Country  Matchcode  P             H
    1 2000      France        0001  1213          1872     
    2 2001      France        0002  1234          2345      
    3 2000      UK            0003  1726          2234      
    4 2001      UK            0004  6433          9082", header=T, stringsAsFactors=F) 
    
    df2 <- read.table(text="
    P    Power
    H    Happiness", header=F, stringsAsFactors=F)
    

    【讨论】:

    • 感谢您的回答,我试过了,但实际上并没有为列名添加标签。我在原始帖子中添加了一张图片以进行澄清。
    【解决方案3】:

    如果您特别想使用循环,这种方法会给出您描述的输出:

    df <- data.frame(Year = c(2000, 2001, 2000, 2001),
                     Country = c("France", "France", "UK","UK"),
                     Matchcode = c("0001", "0002", "0003", "0004"),
                     P = c(1213, 1234, 1726, 6433),
                     H = c(1872, 2345, 2234, 9082))
    
    lookup <- data.frame(code = c ("P", "H"),
                         label = c("Power", "Happiness"),
                         stringsAsFactors = FALSE)
    
    for (i in 1:length(colnames(df))) {
      if(!is.na(match(colnames(df), lookup$code)[i])) {
        Hmisc::label(df[[i]]) <- lookup$label[(match(colnames(df), lookup$code))[i]]
      }
    }
    

    这行得通:

    Hmisc::label(df[4])
    #       P 
    # "Power" 
    

    它还在 RStudio 查看器中检出:

    与其他几位回答者和评论者一样,我最初认为您想将“label =”文本附加到列名。对于任何想要的人,这是(循环)代码。

    for (i in 1:length(colnames(df))) {
      if(!is.na(match(colnames(df), lookup$code)[i])) {
        colnames(df)[i] <- paste0(colnames(df)[i],
                                  "(label=",
                                  lookup$label[(match(colnames(df), lookup$code))[i]],
                                  ")")
      }
    }
    

    【讨论】:

      【解决方案4】:

      我完全不清楚你想用Hmisc::label 做什么,但我认为你误解了Hmisc::label 的角色和功能。

      考虑以下几点:

      1. 让我们构造一个样本data.frame,由 2 行 2 列组成。

        df <- setNames(data.frame(matrix(0, ncol = 2, nrow = 2)), c("a", "b"))
        df
        #  a b
        #1 0 0
        #2 0 0
        
      2. 我们提取列名。 请注意,cn 是一个 character 向量。

        cn <- colnames(df)
        cn
        #[1] "a" "b"
        
      3. 我们现在为cn 设置Hmisc::label

        label(cn) <- "label for cn"
        cn
        #label for cn
        #[1] "a" "b"
        

        我们检查cnattributes

        attributes(cn)
        #$label
        #[1] "label for cn"
        #
        #$class
        #[1] "labelled"  "character"
        
      4. 我们现在将cn 分配给df 的列名。

        colnames(df) <- cn
        df
        #  a b
        #1 0 0
        #2 0 0
        

      注意label 属性如何不作为列名的一部分存储。

      【讨论】:

      • 感谢您的详尽解释。我了解标签不作为列名的一部分存储;然而,它们通常在 Rstudio 查看器中可见。另外,我刚刚发现标签实际上并没有在left_join 中丢失,而是带有一个突变:df &lt;- df%&gt;% group_by(country) %&gt;% mutate_if(is.numeric, funs(d = . - lag(.))) 新的突变变量不再有标签,旧的有(我真的很抱歉只是现在弄清楚了)。
      • 我在原帖里加了一张图更清楚
      【解决方案5】:

      如果您仍然坚持使用 Hmisc,您可以修改“打印”功能以处理标签提供的额外信息,或者更确切地说(并且危害较小)对 R 说必须使用标签打印您的数据。您可以通过创建一个新的数据框类来实现这一点,该类的打印函数行为不同。

      Rstudio 不需要“打印”技巧,因为 Rstudio 本身使用标签和列名。

      df1 = read.table(text = "
        Year      Country  Matchcode  P             H
      1 2000      France        0001  1213          1872     
      2 2001      France        0002  1234          2345      
      3 2000      UK            0003  1726          2234      
      4 2001      UK            0004  6433          9082  ", header=T)
      df2 = read.table(text = "
      var  lab
      P    Power
      H    Happiness", header=T, stringsAsFactors=FALSE)
      
      ## Set the labels of the columns in df1 accordingly to df2
      library(Hmisc)
      for (i in 1:ncol(df1)) {
          lab <- df2[df2$var==colnames(df1)[i],2]
          if (length(lab!=0)) label(df1[[i]]) <- lab
      }
      
      # A print' function dedicated to 'truc' objects
      # Mainly it is the code from the original 'print' except for dimnames[[2L]]
      print.truc <- function (x, ..., digits = NULL, quote = FALSE, right = TRUE, 
      row.names = TRUE) 
        {
        n <- length(row.names(x))
        if (length(x) == 0L) {
          cat(sprintf(ngettext(n, "data frame with 0 columns and %d row", 
              "data frame with 0 columns and %d rows"), n), "\n", 
              sep = "")
          }    
          else if (n == 0L) {
              print.default(names(x), quote = FALSE)
              cat(gettext("<0 rows> (or 0-length row.names)\n"))
          }
          else {
              m <- as.matrix(format.data.frame(x, digits = digits, 
                  na.encode = FALSE))
              if (!isTRUE(row.names)) 
                  dimnames(m)[[1L]] <- if (isFALSE(row.names)) 
                      rep.int("", n)
                      else row.names
              dimnames(m)[[2L]] <- purrr::map(1:ncol(x),
                 function(i) {
                   z <- attributes(x[[i]])$label
                   if (length(z)!=0) z else colnames(x)[i]
                 })
              print(m, ..., quote = quote, right = right)
            }
            invisible(x)
         }
      
      # Says that 'df1' is an 'enhanced' data frame
      class(df1) <- c("truc",class(df1))
      
      # Print as enhanced
      print(df1)
      #  Eyra Country Matchcode Power Happiness
      #1 2000  France         1  1213      1872
      #2 2001  France         2  1234      2345
      #3 2000      UK         3  1726      2234
      #4 2001      UK         4  6433      9082
      
      # Print using standard way
      print(as.data.frame(df1))
      #  Year Country Matchcode    P    H
      #1 2000  France         1 1213 1872
      #2 2001  France         2 1234 2345
      #3 2000      UK         3 1726 2234
      #4 2001      UK         4 6433 9082
      

      【讨论】:

        【解决方案6】:

        不需要Hmisc 的循环,可以在标签命令中使用选项self = FALSE 在一行中执行此操作。

        label(df1[, df2$IndicatorName], self = FALSE) <- df2$IndicatorCode
        

        即。

          
          library(Hmisc, warn.conflicts = FALSE, quietly = TRUE)
          
          df1 = read.table(text = "
        Year      Country  Matchcode  P             H
        1 2000      France        0001  1213          1872     
        2 2001      France        0002  1234          2345      
        3 2000      UK            0003  1726          2234      
        4 2001      UK            0004  6433          9082 
        ", header=T)
          
          df2 = read.table(text = "
        IndicatorName IndicatorCode
        P    Power
        H    Happiness 
        ", header=T)
          
          
          label(df1[, df2$IndicatorName], self = FALSE) <- df2$IndicatorCode
          
          sapply(df1, label)
        #>        Year     Country   Matchcode           P           H 
        #>          ""          ""          ""     "Power" "Happiness"
        

        reprex package (v0.3.0) 于 2020-09-14 创建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-09
          • 1970-01-01
          • 1970-01-01
          • 2018-11-11
          • 1970-01-01
          • 2016-03-10
          • 2021-10-31
          • 1970-01-01
          相关资源
          最近更新 更多