【问题标题】:How do I rearrange values in different columns in an R dataframe如何重新排列 R 数据框中不同列中的值
【发布时间】:2020-06-23 22:39:17
【问题描述】:

我有一个客户数据数据框。它有 3 列电话号码。 类似于下表:

x <- data.frame("Phone1" = c(123,"NULL",245), "Phone2" = c("NULL","NULL",325 ), "Phone3" = c(847,219,"NULL"))
> View(x)
> x
  Phone1 Phone2 Phone3
1    123   NULL    847
2   NULL   NULL    219
3    245    325   NULL

现在,我想重新排列这些列中的值,使 NON-NULL 值排在第一位,并将每条记录的 NULL 值推到最后。这就是我想要的输出:

Phone1 Phone2 Phone3
1    123    847   NULL
2    219   NULL   NULL
3    245    325   NULL

我尝试使用一系列 if 语句来执行此操作,但这需要很长时间,因为我的原始数据框有很多记录。我想知道是否有更简单的方法使用 dplyr 或其他可以帮助解决此问题的软件包。

【问题讨论】:

  • 您的执行结果与您输入的数据不一致:847Phone3,而不是Phone2

标签: r dataframe


【解决方案1】:

您可以将applycy!="NULL"y=="NULL" 的索引一起使用:

t(apply(x, 1, function(y) {i <- y=="NULL"; c(y[!i], y[i])}))
#     [,1]  [,2]   [,3]  
#[1,] "123" "847"  "NULL"
#[2,] "219" "NULL" "NULL"
#[3,] "245" "325"  "NULL"

如果顺序无关紧要(感谢@Daniel-o!):

t(apply(x, 1, sort))
#     [,1]  [,2]   [,3]  
#[1,] "123" "847"  "NULL"
#[2,] "219" "NULL" "NULL"
#[3,] "245" "325"  "NULL"

或者使用列名:

do.call(rbind, lapply(asplit(x, 1), sort))
#     Phone1 Phone3 Phone2
#[1,] "123"  "847"  "NULL"
#[2,] "219"  "NULL" "NULL"
#[3,] "245"  "325"  "NULL"

【讨论】:

  • 或者如果我们不关心保持原来的顺序我们可以简化为t(apply(x,1, function(x) x[order(x)]))
  • @DanielO 谢谢!我插入了较短的t(apply(x, 1, sort))
【解决方案2】:

解决方案有点长,但使用 tidyverse 可以达到预期效果。

我猜您的数据中可能有多个列,而不仅仅是电话列。所以这段代码应该改变你的“PhoneX”列而不是其他列。

如果您已经有一个唯一标识您的客户的列,则可以省略创建 id 列,在这种情况下,将 id 替换为 group_by(id) 函数中的列。

library(tidyr)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

x <- data.frame(Phone1 = c(123,"NULL",245, 456), 
                Phone2 = c("NULL","NULL",325, 893), 
                Phone3 = c(847,219,"NULL", 241))

x %>% 
  mutate(id = row_number()) %>% #make unique identifier
  gather(phone, nr, starts_with("Phone")) %>% #make long format of phone cols
  filter(nr != "NULL") %>% #remove NULLs
  group_by(id) %>% 
  mutate(phone = paste0("Phone", row_number())) %>% 
  spread(phone, nr, fill = "NULL") %>% 
  ungroup()
#> # A tibble: 4 x 4
#>      id Phone1 Phone2 Phone3
#>   <int> <chr>  <chr>  <chr> 
#> 1     1 123    847    NULL  
#> 2     2 219    NULL   NULL  
#> 3     3 245    325    NULL  
#> 4     4 456    893    241

reprex package (v0.3.0) 于 2020-06-23 创建

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-03
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 2018-07-18
    相关资源
    最近更新 更多