R:For循环在列表中起作用,而不是单个元素

时间:2018-06-23 04:39:30

标签: r for-loop

我正在尝试通过编写函数来学习。它将UOM(度量单位)转换为标准UOM的一部分。在这种情况下,为1/10或0.1

我试图遍历从strsplit生成的列表,但是我只得到整个列表,而不是列表中的每个元素。我不知道我在做什么错。是strsplit错误的功能吗?我不认为问题出在strsplit上,但我无法弄清楚我在For循环中做错了什么:

qty<-0
convf<-0
uom <- "EA"
std <- "CA"
pack <-"1EA/10CA"

if(uom!=std){
    s<-strsplit(pack,split = '/')
        for (i in s){
            print(i)
            if(grep(uom,i)){
                qty<- regmatches(i,regexpr('[0-9]+',i))
            }
            if(grep(std,i)){
                convf<-regmatches(i, regexpr('[0-9]+',i))
            }
        } #end for
    qty<-as.numeric(qty)
    convf<-as.numeric(convf)
    }
return(qty/convf)

3 个答案:

答案 0 :(得分:0)

列表的索引可能有问题。在[[1]]函数之后,您是否尝试过使用strsplit

示例:

string <- "Hello/world"
mylist <- strsplit(string, "/")
## [[1]]
## [1] "Hello" "World"

但是,如果我们明确地说希望使用[[1]]列表的第一个“元素”,则将具有字符串的整个数组。

示例:

string <- "Hello/World"
mylist <- strsplit(string, "/")[[1]]
## [1] "Hello" "World"

希望这可以帮助您解决问题。

答案 1 :(得分:0)

这里有一些问题。您遇到的主要问题是s是一个长度为1的列表。在该列表中,第一个(唯一的)元素是一个长度为2的向量。因此,您需要设置i in s[[1]]

但是,我们可以更进一步。尝试以下代码:

library(stringr) 
lapply(strsplit(pack,split = '/'),  # works within the list, can handle larger vectors for `pack`
  function(x, uom, std) {  
    reg_expr <- paste(uom,std, sep = "|") # call this on its own, it's just searching for the text saved in uom or std
    qty <- as.numeric(str_remove(x, reg_expr))  # removes that text and converts the string to a number
    names(qty) <- str_extract(x, reg_expr)  # extracts the text and uses it to name elements in qty

    qty[uom] / qty[std]  # your desired result.
  },
  uom = uom,  # since these are part of the function call, we need to specify what they are.  This is where you should change them.
  std = std)

答案 2 :(得分:0)

我不知道这是否是您要尝试的方法,但是在从类似“ 1EA / 10CA”的字符串中提取数字时,我会避免循环。如果有帮助,列lst实际上是数据集中的一个列表。

library(magrittr)
ds      <- data.frame(pack = c("1EA/10CA", "1EA/4CA", "2EA/2CA"))
pattern <- "^(\\d+)EA/(\\d+)CA$"

ds %>% 
  dplyr::mutate(
    qty     = as.numeric(sub(pattern, "\\1", pack)),
    convf   = as.numeric(sub(pattern, "\\2", pack)),
    ratio   = qty / convf,
    lst     = purrr::map2(qty, convf, ~list(qty=.x[[1]], convf=.y[[1]]))
  )

结果:

      pack qty convf ratio   lst
1 1EA/10CA   1    10  0.10 1, 10
2  1EA/4CA   1     4  0.25  1, 4
3  2EA/2CA   2     2  1.00  2, 2