【问题标题】:data table create row数据表创建行
【发布时间】:2019-03-17 04:10:50
【问题描述】:

我对堆栈溢出进行了广泛的研究,但找不到任何对我想要的输出有用的东西。

为了说明,请考虑以下示例数据框:

      D     X     Y     Z     A     B     C    Total
 1   abc    2     3     4     7     2     1      19

总计对应于每一行的总和。为简单起见,设 B=19,即总数。我想要的输出是:

    D     X     Y     Z     A     B     C    Total
 1  abc   1     2     3     4     5     2      B
 2  N/A   1/B   2/B   3/B   4/B   5/B   2/B    1

这里,第一行中的每个元素除以总数,这反映在第二行中。要为总计创建一列,我使用了 mutate 并这样做了:

df <- df %>% mutate(Total = X + Y + Z + A + B + C)

但我无法弄清楚如何创建一个每个元素都可以被总数整除的行。

任何帮助将不胜感激!我不介意使用 mutate 或 data.table 来执行此操作,因为我使用 data.table 创建了一个大数据框。

EDIT1:我真的很抱歉没有提到这一点,但是一列包含一些字符串。我已经编辑了以上内容以反映这一点。

【问题讨论】:

  • 哎呀,对不起!确实是 1。

标签: r data.table dplyr


【解决方案1】:

这是您的问题的dplyr 答案。您实际想要做的可能更复杂,但这个简单的bind_rowsfiltermutate_all 适用于提供的简单示例。

library(dplyr)
df <- data.frame(x = 2:3, y = 3:4, z = letters[1:2], total = c(0, 19))
bind_rows(
    df,
    filter(df, row_number() == n()) %>%
        mutate_if(is.numeric, funs(. / total))
)

# x         y z total
# 1 2.0000000 3.0000000 a     0
# 2 3.0000000 4.0000000 b    19
# 3 0.1578947 0.2105263 b     1

【讨论】:

  • 谢谢!就像我在上一篇文章中的上述评论(抱歉没有提到这一点),但是如果列包含字符串,这会影响 mutate_all 并且我收到此错误: mutate_impl(.data, dots) 中的错误:评估错误:非数字参数二元运算符。
  • @ynitSed 没问题。请参阅上面我的解决方案中的更新示例。基本上,mutate_if 应该做到这一点,然后只对数字进行操作。
  • 这行得通。如果我有多行并且只想对最后一行执行计算,这会大大改变代码吗?
【解决方案2】:

我又添加了一行以使解决方案更通用。

在基础 R 中,我们可以将数据框除以该行中的 Total 列,然后将 rbind 与原始数据框分开。

new_df <- rbind(df, df/df[, "Total"])
new_df

#           X         Y         Z         A         B          C Total
#1  2.0000000 3.0000000 4.0000000 7.0000000 2.0000000 1.00000000    19
#2  1.0000000 2.0000000 5.0000000 6.0000000 7.0000000 4.00000000    25
#11 0.1052632 0.1578947 0.2105263 0.3684211 0.1052632 0.05263158     1
#21 0.0400000 0.0800000 0.2000000 0.2400000 0.2800000 0.16000000     1

如果订单很重要并且您想维护它,那么我们可以重新排序

rbind(new_df[c(T, F),], new_df[c(F, T),])

#           X         Y         Z         A         B          C Total
#1  2.0000000 3.0000000 4.0000000 7.0000000 2.0000000 1.00000000    19
#11 0.1052632 0.1578947 0.2105263 0.3684211 0.1052632 0.05263158     1
#2  1.0000000 2.0000000 5.0000000 6.0000000 7.0000000 4.00000000    25
#21 0.0400000 0.0800000 0.2000000 0.2400000 0.2800000 0.16000000     1

编辑

如果某些列是字符串,我们可以忽略它们并使用bind_rows 而不是rbind,因为它直接为不匹配的列返回NA

library(dplyr)
bind_rows(df1, df1[!names(df1) %in% "D"]/df1[, "Total"])

#         X         Y         Z         A         B          C  Total    D
#1 2.0000000 3.0000000 4.0000000 7.0000000 2.0000000 1.00000000    19  abc
#2 1.0000000 2.0000000 5.0000000 6.0000000 7.0000000 4.00000000    25  def
#3 0.1052632 0.1578947 0.2105263 0.3684211 0.1052632 0.05263158     1 <NA>
#4 0.0400000 0.0800000 0.2000000 0.2400000 0.2800000 0.16000000     1 <NA>

数据

df <- structure(list(X = c(2, 1), Y = c(3, 2), Z = c(4, 5), A = c(7, 
  6), B = c(2, 7), C = c(1, 4), Total = c(19, 25)), .Names = c("X", 
  "Y", "Z", "A", "B", "C", "Total"), row.names = c("1", "2"), class = "data.frame")

df1 <-structure(list(X = c(2, 1), Y = c(3, 2), Z = c(4, 5), A = c(7, 
6), B = c(2, 7), C = c(1, 4), Total = c(19, 25), D = c("abc", 
"def")), .Names = c("X", "Y", "Z", "A", "B", "C", "Total", "D"
 ), row.names = c("1", "2"), class = "data.frame")

【讨论】:

  • 感谢这个 Ronak!如果一列包含一些字符串,例如在列表中您还说 D = c("a", "b") 并且显然无法执行我想要的计算,我该如何排除此列的计算?跨度>
  • @ynitSed 如果您知道 D 列的列号或df[!names(df) %in% "D"],则可以通过执行 df[-columnnumber]D 列从计算中删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-12
相关资源
最近更新 更多