【问题标题】:how to pass unknown number of arguments to a function in R programming如何在R编程中将未知数量的参数传递给函数
【发布时间】:2014-04-14 13:04:17
【问题描述】:

我正在解析一个包含多列的 csv。 csv 文件中的列数不固定。它从 5 到 10 不等。我需要在函数内重新创建包含这些列的 data.frame。我想知道 R 中是否有像 Ruby(*args) 中的多参数功能。 如果没有,如何实现这个??? 我搜索了一下,发现如果我有一个 col 名称作为

col1
col2

我可以使用:

list <- ls(pat="^col\\d$")

并将此列表作为参数传递给函数,但它只会将列名作为字符传递,而不是这些列名携带的值。

有什么建议吗???

编辑: 我正在解析来自 RoR 应用程序的文件并使用 RinRuby gem 来调用 R 函数。因此,从 ruby​​ 解析 csv 并将单个列内容作为 R 中的单个变量传递。现在在 R 中,我需要创建一个 data.frame。所以实际上它最初不是数据框。因此,在下面的 cal_norm 方法中,我使用名称为 col1、col2、col3 ......等等的循环在 R 中分配变量。

这里是rails代码:

 class UploadsController < ApplicationController

  attr_accessor :calib_data, :calib_data_transpose, :inten_data, :pr_list

  def index
    @uploads = Upload.all

    @upload = Upload.new

  respond_to do |format|
  format.html 
  format.json { render json: @uploads }   
  end
 end

 def create
  @upload = Upload.new(params[:upload]) 

 directory = "public/"
 io_calib = params[:upload][:calib]
 io_inten = params[:upload][:inten]   

 name_calib = io_calib.original_filename
 name_inten = io_inten.original_filename
 calib_path = File.join(directory, "calibs", name_calib)
 inten_path = File.join(directory, "intens", name_inten)

respond_to do |format|
  if @upload.save
    @calib_data, @calib_data_transpose = import(calib_path)
    @inten_data = import_ori(inten_path)
    #probe list of the uploaded file
    @probe_list = calib_data_transpose[0]
    logger.debug @probe_list.to_s
    flash[:notice] = "Files were successfully uploaded!!"
    format.html
    #format.js #{ render json: @upload, status: :created, location: @upload }
  else
    flash[:notice] = "Error in uploading!!"
    format.html { render action: "index" }
    format.json { render json: @upload.errors, status: :unprocessable_entity }
    end
  end
 end

def cal_norm
   #ajax request
   data = params['data'].split(',') 

  for i in 0..@calib_data_transpose.length - 1
  R.assign "col#{i}", @calib_data_transpose[i] 
  end

  R.assign "cells", @inten_data
  R.assign "pr", data
  R.eval <<-EOF

# make sure to convert them in character and numeric vectors

#match the selected pr in the table

#convert the found row of values from data.frame to numeric

#divide each column of the table by the respective pr values and create a new table repat it with different pr.

#make a new table with the ce count and different probe normalization and calculate  for individual pr

#finally return a data.frame with pr names and cell counts

#return individual columns as an array not in the form of matrix/data.frame

EOF

end

def import(file_path)
  array = import_ori(file_path)
  array_splitted = array.map {|a| a.split(",")} 
  array_transpose = array_splitted.transpose
  return array_splitted, array_transpose
end

 def import_ori(file_path)
  string = IO.read(file_path)
  array = string.split("\n")
  array.shift
  return array
 end

end

【问题讨论】:

  • 我不明白这个问题。 read.csv 返回一个 data.frame。
  • 我也没有。您有一个 CSV,每行包含 5 到 10 个项目?您将如何将其放入矩形数据框中?您可以使用fill 参数到read.csv 用NA 标记填充它。否则……什么?
  • 只需使用read.csvread.table 读取您的csv。这两个函数都不关心你的 csv 有多少列。也许您可以将您的问题编辑得更明确一点,就像您所说的“使用这些列重新创建一个 data.frame”的确切含义。
  • 对不起,我没有提到一件事,我正在编辑我的问题。
  • 我认为您需要发布一个来自 Ruby 的示例 - 否则很难弄清楚发生了什么

标签: ruby-on-rails ruby r fastercsv


【解决方案1】:

发布更新问题:

我是 Ruby 的新手,但在这里找到了这个例子:col wise data

这里按列数据被读入 col_data,这里的 0 是 (col) 索引(没有用于测试的 Ruby :( )

require 'csv'
col_data = []
CSV.foreach(filename) {|row| col_data << row[0]}

将 col 数据分配给变量 col1...coln,并为列数创建一个计数器(语法可能不是 100% 正确)

for i in 0..@calib_data_transpose.length - 1
 #R.assign "col#{i}", @calib_data_transpose[i] 
 CSV.foreach(filename) {|row| "col#{i}" << row[i]}
end

R.col_count=@calib_data_transpose.length - 1

创建 col1..coln 后,从 i = 1 开始,一次将列数据组合一个索引。结果将是一个 data.frame,列的顺序为 col1..coln。

R.eval <<-EOF

for(i in 1:col_count) { 
  if (i==1) { 
   df<-data.frame(get(paste0("col",i))) 
  } 
  else { 
   df<-cbind(df,get(paste0("col",i))) 
 } 

 names(df)[i]<-paste0("col",i)
}

EOF

如果这有帮助,请告诉我们...


不再与更新的问题非常相关,但保留它以供后代使用。

给定模式的子集 data.frame

如上所述,Roland read.csv 将读取整个文件,因为您希望控制哪些列保留在 data.frame 中,您可以执行以下操作:

使用data(mtcars)作为样本data.frame

代码:

读入数据:

> data(mtcars)
> head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

对某些条件的数据进行子集化,例如以字母“c”开头的列

> head(mtcars[,grep("^c",colnames(mtcars))])
                   cyl carb
Mazda RX4           6    4
Mazda RX4 Wag       6    4
Datsun 710          4    1
Hornet 4 Drive      6    1
Hornet Sportabout   8    2
Valiant             6    1

这里的'^c' 类似于您问题中的pat="^col\\d$" 模式。您可以将'^c' 替换为您选择的任何正则表达式,例如'^col''^c' 将匹配以字母“c”开头的任何模式,以匹配字符串末尾使用'$c'

【讨论】:

  • Vivek,我编辑了我的问题。对不起,我错过了这个重要的部分
猜你喜欢
  • 2014-11-05
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
  • 2012-01-13
  • 1970-01-01
  • 2014-07-07
  • 2012-06-07
相关资源
最近更新 更多