创建循环以将标签添加到列:library(Hmisc)

Creating a loop to add labels to colums: library(Hmisc)

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

  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  

这是一个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

这行得通。使用%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)

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

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]],
                              ")")
  }
}

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

考虑以下因素:

  1. 让我们构建一个包含 2 行和 2 列的样本 data.frame

    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 属性如何不存储为列名称的一部分。

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

对于本机使用标签和列名的 Rstudio,'print' 技巧不是必需的。

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

不需要使用 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 创建