如何根据另一列中的值创建一列,这些值是我的数据框中的变量名称,我想将其数据填充到 newcol 中? R

How do I create a column based on values in another column which are the names of variables in my dataframe whose data I want to fill newcol with? R

如果我的问题的表述令人困惑,我深表歉意,我一直没能找到类似的线程来阐明我的问题的英文。

我正在处理类似于下面所见的数据样本:

label1 label2 label3 label#
value1 value4 value7 label2
value2 value5 value8 label1
value3 value6 value9 label3

我正在尝试创建一个新列,'currentvalue',它读取特定行中 label# 的值,然后为该行用该行的任何命名列的值填充该列在标签#。换句话说,我希望我的输出看起来像这样:

label1 label2 label3 label# currentvalue
value1 value4 value7 label2 value4
value2 value5 value8 label1 value2
value3 value6 value9 label3 value9

我能想到的唯一解决方案涉及多个 for 循环,我认为这在计算上非常低效。我一直在堆栈溢出中搜索可以帮助我为此编写矢量化解决方案的线程,但我认为我无法很好地阐明问题,因为 none 我的搜索很有帮助。感谢任何帮助(包括帮助更好地说明我的问题)。

有点乱,我想可能有更好的方法,但你可以试试

library(dplyr)
library(tibble)
    
df <- read.table(text = "label1 label2  label3  label#
value1  value4  value7  label2
value2  value5  value8  label1
value3  value6  value9  label3", h = T)

df %>%
  rowwise %>%
  rownames_to_column(., "row") %>%
  mutate(currentvalue = .[[which(rownames(.) == row),which(names(.) == label)]])

  row   label1 label2 label3 label  currentvalue
  <chr> <chr>  <chr>  <chr>  <chr>  <chr>       
1 1     value1 value4 value7 label2 value4      
2 2     value2 value5 value8 label1 value2      
3 3     value3 value6 value9 label3 value9 

当我用read.table读取你的数据时,label#变成了label

栏目名称label#

names(df)[4] <- "label#"

df %>%
  rowwise %>%
  rownames_to_column(., "row") %>%
  mutate(currentvalue = .[[which(rownames(.) == row),which(names(.) == 'label#')]])

  row   label1 label2 label3 `label#` currentvalue
  <chr> <chr>  <chr>  <chr>  <chr>    <chr>       
1 1     value1 value4 value7 label2   label2      
2 2     value2 value5 value8 label1   label1      
3 3     value3 value6 value9 label3   label3  

使用基数 R

x <- match(df$label, names(df))
y <- 1:nrow(df)
z <- data.frame(y, x)
df$currentvalue <- apply(z,1, function(x) df[x[1],x[2]])

时间检查

microbenchmark::microbenchmark(
  a = {
    df %>%
      rowwise %>%
      rownames_to_column(., "row") %>%
      mutate(currentvalue = .[[which(rownames(.) == row),which(names(.) == label)]])
  },
  b = {
    x <- match(df$label, names(df))
    y <- 1:nrow(df)
    z <- data.frame(y, x)
    df$currentvalue <- apply(z,1, function(x) df[x[1],x[2]])
  }
)

Unit: microseconds
 expr    min      lq     mean  median     uq     max neval cld
    a 6157.8 6861.95 8773.098 7465.75 9367.1 26232.8   100   b
    b  360.6  399.75  692.073  488.40  666.9  4225.0   100  a 

使用 dplyrpurrr 的解决方案。 imap_chr 可以通过每一行有效地应用函数。第一个参数是label#中的内容,第二个参数是行号。

通常rowwise当数据帧很大时操作很慢,所以尽量避免rowwise并尽可能使用替代方法。

library(dplyr)
library(purrr)

dat2 <- dat %>%
  mutate(currentvalue = imap_chr(`label#`, ~dat[.y, .x]))
dat2
#   label1 label2 label3 label# currentvalue
# 1 value1 value4 value7 label2       value4
# 2 value2 value5 value8 label1       value2
# 3 value3 value6 value9 label3       value9

数据

dat <- read.table(text = "label1 label2  label3  label
value1  value4  value7  label2
value2  value5  value8  label1
value3  value6  value9  label3", header = TRUE) %>%
  setnames(c("label1", "label2", "label3", "label#"))

最简单的方法是在 rowwise 操作中使用 get 和 dplyr:

library(dplyr)

dat %>% rowwise() %>%
    mutate(curr_value = get(`label#`)) %>%
    ungroup()

# A tibble: 3 × 5
  label1 label2 label3 `label#` curr_value
  <chr>  <chr>  <chr>  <chr>    <chr>     
1 value1 value4 value7 label2   value4    
2 value2 value5 value8 label1   value2    
3 value3 value6 value9 label3   value9