【问题标题】:Extracting nth value from row vector in R从R中的行向量中提取第n个值
【发布时间】:2015-11-14 20:04:34
【问题描述】:

我一直在寻找/考虑一种方法,可以从数据框中的每一行中提取第 n 个值(例如,第 2、第 5、第 7 等)。

例如,我有以下列:

ID   Q1-2013   Q2-2013   Q3-2013  Q4-2013  Q1-2014   Q2-2014   Q3-2014  Q4-2014

在每一列下都有给定的值。我想做的是从四分之一向量(第 2-8 列)中提取每行的第 n 个值。因此,例如,如果我要从每一行中查找第二个值,我想要的公式/函数将从第 2-8 列(2013 年第一季度到 2014 年第四季度)的每一行中提取/提取第二个值。此外,公式/函数也会忽略每行中的空白/NA 值。

【问题讨论】:

  • 我们不想要图片,你可以复制粘贴一小部分原始数据
  • 2,000 5,000 2,500 如果三个值在一行中,我想提取第二个值。
  • 看起来第一个问题将是数据输入。列标题中有空格和美元符号,值中有逗号。由于这是 Excel 的典型情况,因此您可能想在构建 CSV 文件之前查看是否可以在该端进行清理。
  • 好吧,我已经从数据框中删除了逗号(我只是将逗号手动放在这里以使其可读)。话虽如此,列标题不应真正影响公式。我可以简单地使用一个向量,例如[2:8] 拉列。现在我只想在这些列的每一行中提取第二个值。
  • 而且 .... 如果你已经有一个 R 数据框,你应该给我们dput(head(dfrm_name))的输出

标签: r


【解决方案1】:

也许这就是你所追求的。

我首先修改了 iris 数据集,每列都有一些 NA:

iris[] <- lapply(iris, function(x){ x[sample(150, 30, F)] <- NA; x})
head(iris)
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          5.1         3.5          1.4          NA  setosa
#2           NA          NA          1.4          NA  setosa
#3           NA          NA          1.3         0.2  setosa
#4          4.6         3.1          1.5          NA  setosa
#5          5.0         3.6          1.4         0.2  setosa
#6          5.4          NA          1.7         0.4  setosa

然后,要提取每行的第二个非空和非 NA 条目,您可以使用 apply(我知道,不建议在数据帧上使用它,但它确实很麻烦):

apply(iris, 1, function(x) x[which(!is.na(x) & x != "")[2]])
#  [1] "3.5"       "setosa"    "0.2"       "3.1"       "3.6"       "1.7"       "3.4"       "3.4"       "2.9"       "3.1"       "setosa"   
 #[12] "3.4"       "1.4"       "1.1"       "1.2"       "4.4"       "3.9"       "3.5"       "3.8"       "3.8"       "0.2"       "3.7"      
 #[23] "3.6"       "1.7"       "1.9"       "3.0"       "3.4"       "1.5"       "3.4"       "3.2"       "3.1"       "3.4"       "4.1"      
 #[34] "4.2"       "3.1"       "3.2"       "3.5"       "3.6"       "setosa"    "1.5"       "1.3"       "2.3"       "1.3"       "0.6"      
 #[45] "0.4"       "3.0"       "3.8"       "3.2"       "3.7"       "3.3"       "3.2"       "3.2"       "1.5"       "2.3"       "2.8"      
 #[56] "2.8"       "3.3"       "2.4"       "4.6"       "1.4"       "2.0"       "3.0"       "1.0"       "2.9"       "2.9"       "3.1"      
 #[67] "3.0"       "2.7"       "4.5"       "3.9"       "3.2"       "4.0"       "2.5"       "4.7"       "4.3"       "3.0"       "2.8"      
 #[78] "5.0"       "2.9"       "3.5"       "3.8"       "2.4"       "2.7"       "2.7"       "3.0"       "3.4"       "3.1"       "1.3"      
 #[89] "4.1"       "1.3"       "2.6"       "3.0"       "2.6"       "2.3"       "4.2"       "3.0"       "2.9"       "2.9"       "2.5"      
#[100] "2.8"       "3.3"       "2.7"       "3.0"       "2.9"       "3.0"       "3.0"       "4.5"       "2.9"       "5.8"       "3.6"      
#[111] "3.2"       "1.9"       "5.5"       "2.0"       "5.1"       "3.2"       "5.5"       "3.8"       "virginica" "1.5"       "3.2"      
#[122] "2.8"       "2.8"       "2.7"       "2.1"       "6.0"       "2.8"       "3.0"       "2.8"       "5.8"       "2.8"       "3.8"      
#[133] "5.6"       "1.5"       "2.6"       "3.0"       "5.6"       "5.5"       "4.8"       "3.1"       "5.6"       "5.1"       "2.7"      
#[144] "3.2"       "3.3"       "3.0"       "2.5"       "5.2"       "5.4"       "3.0"      

因为apply 将首先将数据框转换为matrix,所以所有列都被转换为相同的类型,在这种情况下为character。您可以稍后将其转换为您想要的任何内容(但请注意,在这种情况下您不能将输出向量直接转换回数字,因为它包含一些字符串,例如“setosa”等)。

【讨论】:

  • 嗨。我是 R 的初学者,所以其中一些对我来说没有意义。在您回复的第一部分中,“lapply(iris, function(x){ x[sample(150, 30, F)]
  • lapply 的第一部分只是为每列添加一些 NA 的一种方式。只是为第二步准备一些数据。实际答案中的apply 是一种在 R 中进行循环的方法,因为我使用了apply(.., 1, ...),它将遍历输入的每一行。解释所有其他内容超出了此答案和评论的范围,因此我建议您查看here 并输入?apply 以阅读帮助页面。另请参阅 R 介绍教程之一。
  • 知道了。太感谢了!这个公式确实有效,我得到了我需要的东西。欣赏!
【解决方案2】:

您还可以使用 convenient 函数 naLast 来自 library(SOfun)

library(SOfun)
dat[dat==''] <- NA #convert all `blank` cells to `NA`
n <- 2 # the row/column index that needs to be extracted
naLast(dat, by='col')[n,] #get the 2nd non-empty/nonNA element for each columns
#V1  V2  V3  V4  V5 
#"G" "B" "B" "B" "C" 

apply 相同

 apply(dat, 2, function(x) x[which(!is.na(x) & x!='')[2]])
 #V1  V2  V3  V4  V5 
 #"G" "B" "B" "B" "C" 

您也可以指定by='row'

naLast(dat, by='row')[,n] #get the 2nd non-empty/nonNA element for each row
#  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20 
#"G" "D" "B" "G" "E" "B" "J" "F" "F" "A" "H" "C" "A" "D" "H" "D" "J" "C" "A" "A" 

数据

set.seed(25)
dat <- as.data.frame(matrix(sample(c(NA,'',LETTERS[1:10]), 
        20*5, replace=TRUE), ncol=5), stringsAsFactors=FALSE)

你可以通过安装包

 library(devtools)
 install_github("mrdwab/SOfun")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 2021-09-14
    相关资源
    最近更新 更多