【问题标题】:Compute, column arrange and select `within` data frame计算、列排列和选择“在”数据框内
【发布时间】:2013-08-04 15:17:32
【问题描述】:

我经常有一个来自某些计算的数据框,我想在输出之前对其进行清理、重命名和列排列。以下所有版本都可以使用,简单的data.frame 最接近。

有没有办法将withinmutate 的数据框内计算与data.frame() 的列顺序保留相结合,而不用在末尾附加和冗余的 [,....]?

library(plyr) 

# Given this chaotically named data.frame
d = expand.grid(VISIT=as.factor(1:2),Biochem=letters[1:2],time=1:5,
                subj=as.factor(1:3))
d$Value1 =round(rnorm(nrow(d)),2)
d$val2 = round(rnorm(nrow(d)),2)

# I would like to cleanup, compute and rearrange columns

# Simple and almost perfect
dDataframe = with(d, data.frame(
  biochem = Biochem,
  subj = subj,
  visit = VISIT,
  value1 = Value1*3 
))
# This simple solution is almost perfect, 
# but requires one more line
dDataframe$value2 = dDataframe$value1*d$val2

# For the following methods I have to reorder 
# and select in a second step

# use mutate from plyr to allow computation on computed values,
# which transform cannot do.
dMutate =   mutate(d,
  biochem = Biochem,
  subj = subj,
  visit = VISIT,
  value1 = Value1*3, #assume this is a time consuming function
  value2 = value1*val2
  # Could set fields = NULL here to remove,
  # but this does not help getting column order
)[,c("biochem","subj","visit","value1","value2")]

# use within. Same problem, order not preserved
dWithin = within(d, {
  biochem = Biochem
  subj = subj
  visit = VISIT
  value1 = Value1*3
  value2 = value1*val2       
})[,c("biochem","subj","visit","value1","value2")]


all.equal(dDataframe,dWithin)
all.equal(dDataframe,dMutate)

【问题讨论】:

  • 在您的简单数据框中,如果更多 col 名称具有大写字母,我将使用 names(d)<-tolower(names(d))
  • 你可以使用 mnel 引入的技巧 with function with。 ... value1 = val1
  • @mnel 的把戏很有趣,我不知道,但没有什么能比得上summarize

标签: r dataframe plyr


【解决方案1】:

您可以使用plyr 包中的summarize(或summarise)。来自文档:

Summarise 以类似的方式进行转换,但它不是向现有数据框添加列,而是创建一个新数据框。 [...]

你的例子:

library(plyr)
summarize(d,
  biochem = Biochem,
  subj    = subj,
  visit   = VISIT,
  value1  = Value1 * 3,
  value2  = value1 * val2       
)

【讨论】:

  • 我知道我错过了一些明显的东西!
【解决方案2】:

如果您愿意转到data.table,那么您可以通过引用执行(大部分)这些操作,并避免与[<-.data.frame$<-.data.frame 相关的复制

setnames 将重命名为 data.tablesetcolorder 将重新排序 data.table:= 将通过引用分配。

library(data.table)
DT <- data.table(d)
# rename to lowercase only
setnames(DT, old = names(DT), new = tolower(names(DT))
# reassign using `:=`
# note the use of `value1<-value1` to allow later use. 
# This will not be necessary once FR1492 has been implemented
# setting to NULL removes these columns
DT[, `:=`(value1 =value1<- value1*3, 
         value2  = value1 * val2, 
         val2 = NULL, time = NULL )]
setcolorder(DT, c("biochem","subj","visit","value1","value2"))

如果您不太关心内存效率,而只想使用data.table 进行语法,那么

DT <- data.table(d)
DT[,list(  biochem = Biochem,   
    subj    = subj,
   visit   = VISIT,
   value1 = value1  <- Value1 * 3,
   value2  = value1 * val2       
   )]

会起作用的。

【讨论】:

  • 这比简单的data.frame 解决方案要详细得多。就效率而言,这可能很好,但summarize 绝对是清晰的赢家。
  • @DieterMenne -- 我添加了一种更简单(内存效率较低)的方法
  • 那个看起来好多了。我记得:永远不要忘记data.table 中的list
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-06
  • 2022-01-19
相关资源
最近更新 更多