【问题标题】:How to remove columns and rows that sum to 0 while preserving non-numeric columns如何在保留非数字列的同时删除总和为 0 的列和行
【发布时间】:2019-01-20 08:48:51
【问题描述】:

以下是我的数据的一个子集。我正在尝试删除总和为 0 的列和行...问题是我想在结果输出中保留第 1 到第 8 列。有任何想法吗?我已经尝试了很多。一个整洁的解决方案将是最好的。

Site    Date    Mon Day Yr          Szn SznYr       A   B   C   D   E   F   G
B0001   7/29/97 7   29  1997    Summer  1997-Summer 0   0   0   0   0   0   0
B0001   7/29/97 7   29  1997    Summer  1997-Summer 0   0   1   0   0   0   0
B0001   7/29/97 7   29  1997    Summer  1997-Summer 0   0   0   3   0   0   0
B0001   7/29/97 7   29  1997    Summer  1997-Summer 0   0   0   0   0   0   10
B0002   7/28/97 7   28  1997    Summer  1997-Summer 0   0   0   0   5   0   0
B0002   7/28/97 7   28  1997    Summer  1997-Summer 0   0   0   0   0   0   0
B0002   7/28/97 7   28  1997    Summer  1997-Summer 0   0   0   0   0   6   0
B0002   7/28/97 7   28  1997    Summer  1997-Summer 0   0   0   0   0   0   0
B0002   7/28/97 7   28  1997    Summer  1997-Summer 0   0   0   0   0   0   0
B0002   7/28/97 7   28  1997    Summer  1997-Summer 0   0   0   0   0   0   8
B0002   6/28/07 6   28  2007    Summer  2007-Summer 0   3   6   1   7   0   1

【问题讨论】:

  • 这些列的总和都不为零
  • 我们应该在检查行的总和之前检查列的总和吗?根据我们的移除顺序,输出可能会有所不同。
  • 编辑数据以使其成为我想要显示的内容。我不确定订单是否重要。
  • 仅供参考,我将 tidyverse 标签更改为 dplyr。 tidyverse 标签 wiki 将向您展示它是为开发该软件包生态系统而保留的,而不是这些软件包的一般用途。如果 dplyr 是不准确的标签,请随时更正。
  • 我们应该先删除行!

标签: r dplyr data-manipulation


【解决方案1】:

试试这个:

# remove rows 
df <- df[rowSums(df[-(1:7)]) !=0, ]
# remove columns    
df <- df[c(1:7,7 + which(colSums(df[-(1:7)]) !=0))]
#     Site    Date Mon Day   Yr    Szn       SznYr B C D E F  G
# 2  B0001 7/29/97   7  29 1997 Summer 1997-Summer 0 1 0 0 0  0
# 3  B0001 7/29/97   7  29 1997 Summer 1997-Summer 0 0 3 0 0  0
# 4  B0001 7/29/97   7  29 1997 Summer 1997-Summer 0 0 0 0 0 10
# 5  B0002 7/28/97   7  28 1997 Summer 1997-Summer 0 0 0 5 0  0
# 7  B0002 7/28/97   7  28 1997 Summer 1997-Summer 0 0 0 0 6  0
# 10 B0002 7/28/97   7  28 1997 Summer 1997-Summer 0 0 0 0 0  8
# 11 B0002 6/28/07   6  28 2007 Summer 2007-Summer 3 6 1 7 0  1

您可以一步完成,以获得与@dan-y 相同的输出(在此特定情况下相同,但如果您的实际数据中有负值,则不同):

    df <- df[rowSums(df[-(1:7)]) !=0,
             c(1:7,7 + which(colSums(df[-(1:7)]) !=0))]

【讨论】:

  • 这行得通!对语法感到好奇。减号有什么作用?
  • 对于负索引,您提到了不想保留的列,因此df[-(1:8)] 保留除前 8 个列之外的所有列
【解决方案2】:

这并不花哨,但它是明确且易于修改的:

# generate example data
df <- data.frame(
    site = c(rep("B1", 4), rep("B2", 7)),
    szn  = rep("Summar", 11),
    A= c(0,0,0,0,0,0,0,0,0,0,0),
    B= c(0,0,0,0,0,0,0,0,0,0,3),
    C= c(0,1,0,0,0,0,0,0,0,0,6),
    D= c(0,0,3,0,0,0,0,0,0,0,1),
    E= c(0,0,0,0,5,0,0,0,0,0,7),
    F= c(0,0,0,0,0,0,6,0,0,0,0),
    G= c(0,0,10,0,0,0,0,0,0,8,1),
    stringsAsFactors = FALSE
)

# get names of cols you want to check for 0s
other_cols <- names(df)[1:2]
num_cols   <- names(df)[3:9]

# check rowsum and colsum
rows_to_keep <- rowSums(df[ , num_cols]) != 0
cols_to_keep <- colSums(df[ , num_cols]) != 0

# keep (1) rows that don't sum to zero 
#      (2) numeric cols that don't sum to zero, and
#      (3) the "other" cols that are non-numeric
df[rows_to_keep , c(other_cols, num_cols[cols_to_keep])]

【讨论】:

  • 您不需要names,只有other_cols &lt;- 1:2num_cols &lt;- 3:9 可以。点赞。
  • 请注意,它可能会给出与我不同的输出,因为我会在删除行后检查要删除的列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
相关资源
最近更新 更多