【问题标题】:Extract value from cell where one column/row value is equal to the column name从一列/行值等于列名的单元格中提取值
【发布时间】:2019-02-04 14:49:54
【问题描述】:

我已经看到了几个关于解决此问题的线程,但我正在努力实施它们。我有一个 df,顶部有列和描述,然后我有一个样本列表,其中包含按描述分组的数据。我需要提取描述与列名匹配的值。

我尝试了不同的解决方案,使用 match、cbind、sapply...等,但收到有关无效类型(矩阵)或重复行名的错误。

 df1
 #row   description    sample    ball   square    circle
 1      ball           1a        .78      .04      .22
 2      ball           7b3       .32      .33      .33
 3      square         aaabc     .02      .90      .05
 4      circle         ggg3      .05      .04      .90
 5      circle         44        .01      .25      .70

我的输出是:

 df2
 #row   description    sample    value
 1      ball           1a        .78      
 2      ball           7b3       .32      
 3      square         aaabc     .90      
 4      circle         ggg3      .90
 5      circle         44        .70

然后更进一步,我会过滤它

 df2 %>%
 filter(value < .9) %>%
 select(description, sample, value)

导致:

 #row   description    sample    value
 1      ball           1a        .78      
 2      ball           7b3       .32      
 3      circle         44        .70

我知道这是重复的,我只是对为什么我无法获得使用此数据集的解决方案一无所知。

【问题讨论】:

标签: r filter match sapply cbind


【解决方案1】:

我们可以使用行/列索引来提取match列名与“描述”列值的值

m1 <- cbind(seq_len(nrow(df1)), match(df1$description, names(df1)[3:5]))
data.frame(df1[1:3], value = df1[3:5][m1])
#  description sample ball value
#1        ball     1a 0.78  0.78
#2        ball    7b3 0.32  0.32
#3      square  aaabc 0.02  0.90
#4      circle   ggg3 0.05  0.90
#5      circle     44 0.01  0.70

tidyverse

library(tidyverse)
df1 %>% 
   rowwise %>% 
   transmute(description, sample, value = get(description))
# A tibble: 5 x 3
#  description sample value
#  <chr>       <chr>  <dbl>
#1 ball        1a      0.78
#2 ball        7b3     0.32
#3 square      aaabc   0.9 
#4 circle      ggg3    0.9 
#5 circle      44      0.7 

数据

df1 <- structure(list(description = c("ball", "ball", "square", "circle", 
 "circle"), sample = c("1a", "7b3", "aaabc", "ggg3", "44"), ball = c(0.78, 
 0.32, 0.02, 0.05, 0.01), square = c(0.04, 0.33, 0.9, 0.04, 0.25
 ), circle = c(0.22, 0.33, 0.05, 0.9, 0.7)), class = "data.frame", 
  row.names = c("1", 
  "2", "3", "4", "5"))

【讨论】:

  • 谢谢! cbind 解决方案给了我同样的问题,我已经遇到了。“我是无效类型(矩阵)。也许将来一个 2 列矩阵可以返回一个 DT 元素列表(本着 FAQ 2.14 中的 A[B] 的精神) ). 如果您愿意,请向 data.table 问题跟踪器报告,或将您的 cmets 添加到 FR #657。”但是 tidyverse 解决方案是完美的!
  • @Steve 看起来你有一个data.table。在这种情况下,您需要setDF(df1),然后使用相同的代码或使用with = FALSE 对列进行子集化
【解决方案2】:

您似乎有百分比的可能性。因此,您基本上是在尝试提取出现可能性最高的列,例如提取这 3 行中每行的最大值。所以:

首先我们创建一个函数来提取 3 列中每行的最大值

    funcionMax <- function(unDf) {
  numFilas <- nrow(unDf)
  vectorMax <- vector()

  for(i in 1:numFilas)
  {
    vectorMax[i]<- max(unDf[i,1],unDf[i,2],unDf[i,3])

  }
  vectorMax
}

然后,我们只处理这 3 列的子集,并应用新函数:

vectorFuncionMax <- df %>% select(ball,square,circle) %>% funcionMax
cbind(df,vectorFuncionMax)

就是这样。不客气。

【讨论】:

  • 感谢您的回答!不幸的是,我对每一行中的最高值不感兴趣。 (在不同的描述中,第 2 行的值更高。)
  • 如果是这种情况,那么另一种对我来说听起来合乎逻辑的方法是使用 collect from dplyr 将列名放入单个列并用它创建一个 df。然后使用merge得到对应的值。
猜你喜欢
  • 2020-01-15
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多