【问题标题】:Calculation via factor results in a by-list - how to circumvent?通过因子计算会产生一个列表 - 如何规避?
【发布时间】:2017-12-01 10:23:29
【问题描述】:

我有一个如下的data.frame:

  Lot Wafer Voltage Slope Voltage_irradiated Slope_irradiated m_dist_lot
1   8   810   356.119 6.08423    356.427           6.13945          NA
2   8   818   355.249 6.01046    354.124           6.20855          NA
3   9   917   346.921 6.21474    346.847           6.33904          NA
4 (...)
120 9   914   353.335 6.15060    352.540           6.19277          NA 
121 7   721   358.647 6.10592    357.797           6.17244          NA
122 (...)

我的目标很简单,但也有点困难。绝对可以通过以下几种方式解决它: 我想根据一个因素对每一行应用一个函数“func”,例如因素“很多”。这是通过

m_dist_lot<- by(data.frame, data.frame$Lot,func)

这确实有效,但结果是一个列表:

data.frame$Lot: 7

      354       355       363       367       378       419       426       427       428       431       460       477       836 
3.5231249 9.4229589 1.4996504 7.2984485 7.6883170 1.2354754 1.8547674 3.1129814 4.4303001 1.9634573 3.7281868 3.6182559 6.4718306 

data.frame$Lot: 8
         1          2         11         15         17         18         19         20         21         22         24         25 
 2.1415352  4.6459868  1.3485551 38.8218984  3.9988686  2.2473563  6.7186047  2.6433790  0.5869746  0.5832567  4.5321623  1.8567318 

第一行似乎是从中获取数据的初始 data.frame 的行。第二行是计算值。 我现在的问题是:如何根据正确的行将这些值正确存储到原始 data.frame 中?

例如在数据框的某个计算/行的情况下:

m_dist_lot<- by(data.frame, data.frame$Lot,func)

data.frame 中第二行的结果

data.frame$Lot: 8
2
4.6459868

我想根据正确的行“2”将值4.6459868存储在data.frame$m_dist_lot中:

  Lot Wafer Voltage Slope Voltage_irradiated Slope_irradiated m_dist_lot
1   8   810   356.119 6.08423    356.427           6.13945          NA
2   8   818   355.249 6.01046    354.124           6.20855     4.6459868
3   9   917   346.921 6.21474    346.847           6.33904          NA
4 (...)
120 9   914   353.335 6.15060    352.540           6.19277          NA 
121 7   721   358.647 6.10592    357.797           6.17244          NA
122 (...)

但我不知道怎么做。实际上,我最好的尝试是使用“unlist”。

un&lt;- unlist(m_dist_lot) 结果

un[1]
6.354 
3.523125 
un[2]
6.355 
9.422959 
un[3]
(..)

但我仍然不知道如何“分离”“factor.row”和“calculated”值的信息,以便将信息正确存储在数据框中。

至少在使用un&lt;- unlist(m_dist_lot, use.names = FALSE) 时,这些因素不存在:

un[1]
3.523125
un[2]
9.422959
un[3]
1.49965
(..)

但现在我缺乏如何将这些值正确分配到 data.frame 中的信息。

使用un&lt;- do.call(rbind, lapply(m_dist_lot, data.frame, stringsAsFactors=FALSE)) 会导致

(...)
7.922    0.94130936
7.976    4.89560441
8.1      2.14153516
8.2      4.64598677
8.11     1.34855514
(...)

这里我仍然缺少计算值的正确分配 data.frame。 我确信必须有一个可行的方法。你知道什么好方法吗?

【问题讨论】:

    标签: r


    【解决方案1】:

    没有可重复的数据或您希望func 执行的示例,我在这里猜测了一下。不过,我认为dplyr 将成为您的答案。

    首先,我将使用来自dplyr(从magrittr 导出)的管道(%&gt;%)通过一系列函数传递内置的iris 数据。 如果您要计算的内容需要完整的 data.frame(而不仅仅是一两列),您可以修改此方法以执行您想要的操作(只需编写函数来获取数据。帧,添加感兴趣的列,然后返回完整的数据帧)。

    在这里,我首先 split iris 按物种划分数据(这会创建一个列表,每个物种都有一个单独的 data.frame)。接下来,我使用lapply 对列表的每个元素运行head 函数。这将返回一个 data.frames 列表,现在每个只有三行。 (您可以在此处将 head 替换为您感兴趣的函数,只要它返回完整的 data.frame。)最后,我将列表的每个元素与 bind_rows 缝合在一起。

    topIris <-
      iris %>%
      split(.$Species) %>%
      lapply(head, n = 3) %>%
      bind_rows()
    

    这会返回:

      Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
    1          5.1         3.5          1.4         0.2     setosa
    2          4.9         3.0          1.4         0.2     setosa
    3          4.7         3.2          1.3         0.2     setosa
    4          7.0         3.2          4.7         1.4 versicolor
    5          6.4         3.2          4.5         1.5 versicolor
    6          6.9         3.1          4.9         1.5 versicolor
    7          6.3         3.3          6.0         2.5  virginica
    8          5.8         2.7          5.1         1.9  virginica
    9          7.1         3.0          5.9         2.1  virginica
    

    我将用它来说明我认为可以真正解决您的根本问题的方法。

    来自dplyrgroup_by 函数允许使用类似的方法,但不必split data.frame。当对 data.frame 进行分组时,应用于它的任何函数都将按组单独应用。这是一个实际的例子,它对每个物种的萼片长度进行排名。这显然不是直接有用,但是您可以编写一个自定义函数,该函数将任意数量的列作为参数(然后作为向量传入)并返回相同长度的向量(以创建新列或更新现有列一)。最后的select 函数只是为了更容易看到我做了什么

    topIris %>%
      group_by(Species) %>%
      mutate(rank_Sepal_Length = rank(Sepal.Length)) %>%
      select(Species, rank_Sepal_Length, Sepal.Length)
    

    返回:

         Species rank_Sepal_Length Sepal.Length
          <fctr>             <dbl>        <dbl>
    1     setosa                 3          5.1
    2     setosa                 2          4.9
    3     setosa                 1          4.7
    4 versicolor                 3          7.0
    5 versicolor                 1          6.4
    6 versicolor                 2          6.9
    7  virginica                 2          6.3
    8  virginica                 1          5.8
    9  virginica                 3          7.1
    

    【讨论】:

      【解决方案2】:

      我在Force gsub to keep trailing zeros 的帮助下找到了解决方法:

      un<- do.call(rbind, lapply(list, data.frame, stringsAsFactors=FALSE))
      un<- gsub(".*.","", un)
      un<- regmatches(un, gregexpr("(?<=.).*", un, perl=TRUE))
      
      rows<- data.frame(matrix(ncol = 1, nrow = lengths(un)))
      colnames(rows)<- c("row_number")
      rows["row_number"]<- sprintf("%s", rownames(un))
      rows["row_number"]<- as.numeric(un[,1])
      rows["row_number"]<- sub("^[^.]*[.]", "", format(rows[,1], width = max(nchar(rows[,1]))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-31
        • 1970-01-01
        • 2020-08-17
        • 2011-11-18
        • 2018-01-24
        • 2020-09-12
        • 1970-01-01
        相关资源
        最近更新 更多