【问题标题】:R loop - how to use it correctly?R循环 - 如何正确使用它?
【发布时间】:2015-05-23 14:08:13
【问题描述】:

我来自 PHP 背景,但仍在尝试了解 R。

例如,我可以轻松地在 PHP 中循环一个数组并操作数据,

$array = [
  "site1"   => 9
  "site2"   => 10
  "site3"   => 18
  "site4"   => 28
]

foreach($array as $index => $id) {
   echo $id . '<br/>'; 
}

结果,

9 
10 
18 
28

但在 R 中,例如,我有这个数据框,

    siteKey siteCode
1   site1   9
2   site2   10
3   site3   18
4   site4   28

循环,

for(i in 1:length(sites.df$siteKey)) {
    print(sites.df$siteCode)
}

结果,

[1] "9"  "10" "18" "28"
[1] "9"  "10" "18" "28"
[1] "9"  "10" "18" "28"
[1] "9"  "10" "18" "28"

我以为应该是下面这个结果?

"9"  
"10" 
"18" 
"28"

知道如何使用 R 循环来获得所需的结果吗?

编辑:

查询,

  # Prepare SQL query1.
  dataQuery <- "SELECT 
                *
            FROM speckdata AS s

            LEFT JOIN weatherunderground AS w 
            ON s.wid_timestamp = w.wid_timestamp

            LEFT JOIN nodes AS n 
            ON n.nid = s.nid
            AND n.datatype = 'speck'

            WHERE n.nid = 'SITE'
            "

也许在下面循环这个更好?

  #
  # Data: site 1
  #

  # Match the pattern and replace it.
  data1Query <- sub("SITE", as.character(site1), data1Query)

  # Store the result in data1.
  data1 = dbGetQuery(DB, data1Query)

  #
  # Data: site 2
  #

  data2Query <- sub("SITE", as.character(site2), data2Query)

  # Store the result in data.
  data2 = dbGetQuery(DB, data2Query)

  #
  # Data: site 3
  #

  data3Query <- sub("SITE", as.character(site3), data3Query)

  # Store the result in data.
  data3 = dbGetQuery(DB, data3Query)

  #
  # Data: site 4
  #

  data4Query <- sub("SITE", as.character(site4), data4Query)

  # Store the result in data.
  data4 = dbGetQuery(DB, data4Query)

然后合并所有数据,

      # Merge data sets.
      set.seed(1)
      dataList = list(data1, data2, data3, data4)
      allData = Reduce(function(...) merge(..., all=T), dataList)

然后绘制数据,

           timePlot(
                allData,
                pollutant = c(species, condition), 
                avg.time = mean,
                lwd = 2,
                lty = 1,
                type = "site",
                group = TRUE,
                auto.text = FALSE
            )

【问题讨论】:

  • 不需要循环的解决方案。 writeLines(as.character(sites.df$siteCode))
  • 我同意其他 cmets。如果您的目标是打印siteCode 列中的值,那么绝对没有理由使用循环。事实上,您已经使用了适当的代码,即print(sites.df$siteCode)。为什么您觉得需要将其包装在一个循环中尚不清楚。如果目标不是打印,您需要在问题中指定它。但是,很有可能您仍然不需要循环。阅读The R Inferno
  • 为您更广泛的问题创建一个可重复的示例。不仅仅是代码的sn-ps。例如dataQuery 的值?提供一些数字我们可以尝试的方法。
  • lapply 就是为此而设计的。像lapply(sites.df$siteKey, function(x) { data1Query &lt;- sub("DATE1", as.character(date_from), dataQuery); data1Query &lt;- sub("DATE2", as.character(date_to), data1Query); sub("SITE", as.character(x), data1Query) }) 这样的东西。 (未测试,因为没有可重现的示例。)
  • sub 的用法可能会被赋值替换。 data1Query &lt;- sub("DATE1", as.character(date_from), dataQuery) 可以变成data1Query$DATE1 &lt;- as.character(dataQuery$data_from)。但同样,没有具体的例子,这只是猜测。

标签: php r for-loop shiny


【解决方案1】:

像这样在循环中添加对 [i] 的调用...

for(i in 1:length(sites.df$siteKey)) {
    print(sites.df$siteCode[i])
}

这样,每次迭代都会在位置 [i] 打印单个实例。

希望这是有道理的。

【讨论】:

  • 最好的教训是学习 R 如何让你避免它。
  • 您是否将其放在循环中?因为你不应该。使用点菜
  • 您不应该将我的代码放在 for 循环中。只需单独输入即可。
  • @plafort 我需要循环,因为我还需要循环其他东西。
【解决方案2】:

@dsifford 的解决方案在 base R 中是可以的。但是,我建议在从 php 切换的早期查看 dplyr 包,因为它比 xapply 的无望混乱更透明函数(向所有激进的 base-R-ers 道歉)。

library(dplyr)
site.df = data.frame(siteKey = paste0("site",1:4), siteCode = runif(4,9,28))

site.df %>%
  rowwise %>%
  do(print(.$siteCode))

这本身并不容易,但如果你有额外的操作,它会让骑行更顺畅。

【讨论】:

  • *apply 函数的一个特点是它们比for 循环更透明——我不是激进的base-R。虽然我同意 dplyr 值得一看,但在这个特定的示例中,我认为它不会使其更加透明。也许你可以加入基准来展示一些潜在的优势。
  • 什么是radical base-R-ers btw?你如何定义它们?
  • 您可以在上面的 cmets 部分找到激进的 base-R-ers:他们将 xapply 定义为福音,将 for-loops 定义为魔鬼。事实更复杂,请参阅 R.r-project.markmail.org/thread/o3vz2tlm2z22og27 早年的数十个 cmets。当速度无关紧要时,我使用 for 循环,并且 xapply 的范围规则和非幂等性(返回是列表,必须使用 do.call(rbind..))妨碍了。 dplyr 是 xapply 一致的方式。
  • @jangorecki:可以肯定,这会更慢,当重要时,我会检查。没关系的时候,我在浪费的几毫秒内喝了一杯咖啡。但是请注意,我提到了dplyr/rowwise as a special case of a grouping operator which is useful if you do other things in the %>%` 链。不是因为速度。
【解决方案3】:

您写的问题是“R 循环:如何正确使用它?”

你提出这个代码

for(i in 1:length(sites.df$siteKey)) {
    print(sites.df$siteCode)
}

此代码将是正确使用 R 循环的示例(如果您坚持这样做,即使不鼓励这样做)。

这段代码的意思是,每次通过打印出 $siteCode 的“列”或完整的值列表。循环会为每个站点重复打印请求,因此每次传递都会获得相同的完整列表。

正如上面@dsifford 建议的那样,将其更改为

for(i in 1:length(sites.df$siteKey)) {
    print(sites.df$siteCode[i])
}

这意味着它不会打印整个列表,而是只打印该列表中每次传递的第 ith 个值。

您添加的新代码存在不同的问题,特别是您为每个站点一遍又一遍地重复相同的代码。您可能需要考虑编写函数来替换重复的代码,然后将这些函数提供给您正在使用的站点列表。在这种情况下,循环可能有意义(尽管可能没有意义)。但这只是您最初问题的一个附带问题。

【讨论】:

    猜你喜欢
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 2019-02-15
    • 2020-12-05
    • 2016-04-10
    相关资源
    最近更新 更多