【问题标题】:I want to dissociate lists in a data frame into single values to different columns in R我想将数据框中的列表分解为 R 中不同列的单个值
【发布时间】:2020-07-01 18:13:13
【问题描述】:

我有一个这样的数据库:

d <- c(01, 02, 03, 04)
h <- c("19:00", "19:00", "07:00", "07:00")
p1 <- c(123, 321, 123, 123)
p2 <- c(321, 345, 567, 567)

df <- data.frame(date = d, hours = h, person1 = p1, person2 = p2)

我使用这段代码将每个person1的所有特征关联到不同的列中:

已编辑:rn = rowid(person1, date, hours) 是实际代码。不是rn = rowid(person1)

library(dplyr)
library(data.table)
library(tidyr)

df1 <- df %>% 
  mutate(rn = rowid(person1, date, hours)) %>% 
  pivot_wider(names_from = rn, values_from = c(date, hours, person2),
              names_sep="")

但是这段代码给了我这个输出:

# person1    date1        hours1                            person21

# 123        c(1,3,4)     c("19:00", "07:00", "07:00")      c(321,567,567)

# 321        2            19:00                             345     

我不希望它重复像 07:00567 这样的值。我希望它在不同的列中给我每个不同的值,忽略重复的值。如果可能的话,像这样组织:

# person1 date1  date2 date3  date4...  hours1  hours2 ... person21  person22   person23   person24

# 123     01     NA    03     04        07:00   19:00      NA        321        NA         567

# 321     NA     02    NA     NA        NA      19:00      NA        NA         345        NA

person21、22、23 和 24 分别是我的df1$person1 的第一、二、三、四等人。

但对我来说理想的输出应该是这样的:

# person1 d01  d02  d03  d04 ...  h07:00  h19:00 ... p123  p321   p345  p567

# 123     1    0    1    1   ...  1       0      ... 1      0     0     1

# 321     0    1    0    0   ...  0       0      ... 1      0     0     1     

我该怎么做?

【问题讨论】:

  • 代码没有给我一个列表
  • @akrun 我现在以正确的方式编辑它。正确的代码实际上是您在旧帖子中给我的第二个建议。
  • 在最后一个代码块中,您提到了ideal output。我试图在下面的解决方案中获得该输出
  • 啊,好的。代码几乎是我想要的。我只是希望它不注册重复的值。正如您在我昨天的帖子中所建议的那样,您可以使用我在 mutate(rn = rowid(person1, date, hours)) 而不是 mutate(rn = rowid(person1)) 中编辑的代码更好地了解正在发生的事情。它给了我那些 c("19:00", "07:00", "07:00") c(321,567,567) 列表。
  • 我更新了下面的解决方案。它看起来像您的预期输出

标签: r dataframe dplyr data-manipulation


【解决方案1】:

如果我们要返回二进制输出,请在pivot_wider 中指定values_fnvalues_fill

library(dplyr)
library(tidyr)
library(data.table)
df %>% 
 mutate(rn = rowid(person1)) %>% 
 pivot_wider(names_from = rn, values_from = c(date, hours, person2),
        names_sep="", values_fn = length, values_fill = list(date = 0, hours = 0, person2 = 0))
# A tibble: 2 x 10
#   person1 date1 date2 date3 hours1 hours2 hours3 person21 person22 person23
#     <dbl> <int> <int> <int>  <int>  <int>  <int>    <int>    <int>    <int>
#1     123     1     1     1      1      1      1        1        1        1
#2     321     1     0     0      1      0      0        1        0        0

如果我们希望值也是列名,一个选项是先重塑为“长”格式,然后在转换后执行pivot_wider

df %>% 
   mutate(date = sprintf("%02d", date)) %>%
   mutate(across(where(is.numeric), as.character)) %>% 
   pivot_longer(cols = -person1) %>% 
   mutate(name = substr(name, 1, 1)) %>% 
   unite(name, name, value, sep="") %>% 
   distinct(person1, name) %>%
   mutate(n = 1) %>% 
   pivot_wider(names_from = name, values_from =n, values_fill = list(n = 0))
# A tibble: 2 x 10
#  person1   d01 `h19:00`  p321   d02  p345   d03 `h07:00`  p567   d04
#  <chr>   <dbl>    <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl> <dbl> <dbl>
#1 123         1        1     1     0     0     1        1     1     1
#2 321         0        1     0     1     1     0        0     0     0

【讨论】:

  • 太棒了!是否可以自动将 colnames 更改为表中的等效值?比如,我希望它不是hours1,而是07:00。这是因为列的数量是巨大的,我会花费一生的时间来编辑它
  • @ApoloReis 更新了解决方案。你现在可以检查一下。谢谢
  • 完美运行!!!我只需要在原始表中将%02d 更改为%02s,否则它会返回错误Erro: Problem with `mutate()` input `Data`. x formato inválido'%02d'; use o formato %s para objetos caractere i Input `Data` is `sprintf("%02d", Data)`.。我不认为它会是原始表的问题,对吧?非常感谢! @akrun
  • @ApoloReis 这可能是因为你的“日期”是原始数据集中的字符串,这里是整数
猜你喜欢
  • 2021-11-07
  • 2020-03-28
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 2018-02-19
  • 2020-07-14
  • 2019-12-25
相关资源
最近更新 更多