【问题标题】:Shift cells in a data frame to the right based on row values根据行值将数据框中的单元格向右移动
【发布时间】:2019-07-31 16:42:33
【问题描述】:

我正在使用一个数据框,该数据框是从多个制表符分隔的文本文件创建的,这些文本文件导入为使用 rbind 连接在一起的小标题。这些文件都包含相似的列名,但由于在创建这些文件时添加了 cmets,某些值在导入时位于错误的列下。我正在尝试将非注释单元格值移动到它们相邻的右列。我无法以任何方式更改原始文件。

初始示例数据框代码:

df1<-df<-data.frame(
  c1=c("A","B","C",1,1,1),
  c2=c(1,1,1,5,NA,5),
  c3=c(5,5,5,"C","C","C"),
  c4=c("C","C","C",NA,NA,NA)
)

df2<-data.frame(
  c1=c("A","B","F",2,2,2),
  c2=c(2,2,2,6,6,6),
  c3=c(6,6,6,"D","D","D"),
  c4=c("D","D","D",NA,NA,NA)
)

初始示例数据框:

> df1
  c1 c2 c3   c4
1  A  1  5    C
2  B  1  5    C
3  C  1  5    C
4  1  5  C <NA>
5  1 NA  C <NA>
6  1  5  C <NA>
> df2
  c1 c2 c3   c4
1  A  2  6    D
2  B  2  6    D
3  F  2  6    D
4  2 NA  D <NA>
5  2  6  D <NA>
6  2  6  D <NA>

编译的数据框代码:

df<-rbind(df1,df2)

编译的数据框:

> df
   c1 c2 c3   c4
1   A  1  5    C
2   B  1  5    C
3   C  1  5    C
4   1  5  C <NA>
5   1 NA  C <NA>
6   1  5  C <NA>
7   A  2  6    D
8   B  2  6    D
9   F  2  6    D
10  2 NA  D <NA>
11  2  6  D <NA>
12  2  6  D <NA>

所需的数据框:

     c1 c2 c3 c4
1     A  1  5  C
2     B  1  5  C
3     C  1  5  C
4  <NA>  1  5  C
5  <NA>  1 NA  C
6  <NA>  1  5  C
7     A  2  6  D
8     B  2  6  D
9     D  2  6  D
10 <NA>  2 NA  D
11 <NA>  2  6  D
12 <NA>  2  6  D

要移动的第一列上的 cmets 和重复行并不总是相同的长度或相同的值,也不总是数字。

我尝试使用类似问题的修改版本来改变我的价值观。 Using R to shift values to the left of data.frame

df[]<-t(apply(df, 1, function(x) c(x[is.na(x)], x[!is.na(x)])))

但是,此代码使用所有 NA 值,并且某些列包含 NA 值,因此这仅在最后一列是 NA 而不是任何其他列时才有效。

> df
     c1   c2 c3 c4
1     A    1  5  C
2     B    1  5  C
3     C    1  5  C
4  <NA>    1  5  C
5  <NA> <NA>  1  C
6  <NA>    1  5  C
7     A    2  6  D
8     B    2  6  D
9     F    2  6  D
10 <NA> <NA>  2  D
11 <NA>    2  6  D
12 <NA>    2  6  D

有没有办法让这段代码只使用最后一列作为指导来将相应的单元格向右移动?

编辑:从类似问题 df1 修改代码的拼写错误更改为 df

【问题讨论】:

  • 您的c1 中的值是否在您的真实数据集中字母和c2 数字中?如果是这样,我可以看到将带有c1 的行过滤为字母,重命名列,然后将它们重新绑定在一起。
  • 不幸的是,它各不相同。有时它们是字符,有时它们是数值。它不是创建原始文件的最一致的系统。
  • 如果它以某种模式变化,即使不是字母与数字,您也可以考虑使用正则表达式过滤事物的方法。或者也许过滤包含NA的最后一列?我认为这适用于您的示例数据集。我也对原始文件的样子有点好奇,主要是为了在导入步骤中有一些方法可以解决这个问题。 :)
  • 没有固定的模式,但有些 cmets 有重复字符。我能够调整 t(apply( 行以使用 grepl 而不是带有多个字符的 is.na(x) 来搜索这些字符并以这种方式排列。它需要一些工作,因为您需要提前知道一些 cmets 是什么。

标签: r sorting dataframe data-manipulation tibble


【解决方案1】:

更新:这是解决方案。这有点麻烦,但它确实有效。为了保留初始顺序,一个好主意是将索引设置为列并用它对最终的 df 进行排序。稍后,您可以通过column_to_rownames 或简单地使用select(df, -c('index')) 将列恢复为索引。有了这个,我希望我回答了这个问题。

df <- rbind(df1,df2)
df <- mutate_all(df, as.character)
df <- rownames_to_column(df, 'index')

df_ok <- filter(df, !is.na(c4))
df_na <- filter(df, is.na(c4))
df_fin <- df_na %>%
 select(c4, everything()) %>%
 rename(c1 = c4, c2 = c1, c3 = c2, c4 = c3) %>%
 rbind(df_ok)
df_fin <- df_fin %>%
 mutate(index = as.integer(index)) %>%
 arrange(index)

【讨论】:

  • 这会让列很好地拥有他们需要的值。我尝试添加的一件事是%&gt;% arrange(c2,c1) 尝试使数据框具有与示例相同的顺序。它确实将 c1 中的 cmets 放在了它们各自 c2 的顶部,但 c1 与示例所在的顺序不同。添加的顺序为:[1] "C" "A" "B" NA NA NA "A" "B" "F" NA NA NA。我不确定.by_group 参数是否对此有所帮助。
  • 这很好用。谢谢你的帮助。我在末尾添加了select 以删除index,但这非常有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多