有替代的r基函数来替代pivot_wider吗?

问题描述 投票:0回答:3

我有以下类型的表格:

经济特区 班级 瓦尔
1_1_1 1 2
1_1_1 5 2
1_1_2 5 2
1_1_3 1 1
1_1_3 5 2
1_1_4 1 1
1_1_5 2 1
1_2_1 1 2
1_2_1 5 2

为了将“Class”列分散到多个新列中,从“Val”列中获取价值,我使用了pivot_wider,一切顺利。我输入了这个代码:

pivot_wider(names_from = Class, values_from = Val, names_sort=T, values_fill = list(n = 0))

获得这样的结果:

塞兹 1 2 3 4 5 6 7
1_1_1 2 0 0 0 2 0 0
1_1_2 0 0 0 0 2 0 0
1_1_3 1 0 0 0 2 0 0

不幸的是,我必须使用外部计算机,其中只有基本的 R 包,并且请求附加包的时间并不短。

我尝试使用这个解决方案:

newdata <- xtabs(dat$Val ~ dat$Sez + dat$Class)

但它给了我每行的频率分布:

经济特区 班级 频率
1_1_1 1 2
1_1_2 1 0
1_1_3 1 1
1_1_4 1 1
1_1_5 1 0
1_2_1 1 1

我正在寻找一种具有 R 基本功能的解决方案,它为我提供了一个与使用ivot_wider 时使用的对象相同的对象。

r pivot
3个回答
6
投票

我们将“类”创建为

factor
并使用
xtabs

df1$Class <- factor(df1$Class, levels = 1:7)

 xtabs(Val ~ SEZ + Class, df1)

-输出

      Class
SEZ     1 2 3 4 5 6 7
  1_1_1 2 0 0 0 2 0 0
  1_1_2 0 0 0 0 2 0 0
  1_1_3 1 0 0 0 2 0 0
  1_1_4 1 0 0 0 0 0 0
  1_1_5 0 1 0 0 0 0 0
  1_2_1 2 0 0 0 2 0 0

如果我们需要

data.frame
输出

out <- as.data.frame.matrix( xtabs(Val ~ SEZ + Class, df1))
out$SEZ <- row.names(out)
row.names(out) <- NULL

数据

df1 <- structure(list(SEZ = c("1_1_1", "1_1_1", "1_1_2", "1_1_3", "1_1_3", 
"1_1_4", "1_1_5", "1_2_1", "1_2_1"), Class = c(1L, 5L, 5L, 1L, 
5L, 1L, 2L, 1L, 5L), Val = c(2L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 
2L)), row.names = c(NA, -9L), class = "data.frame")

1
投票

另一个基本 R 选项使用

reshape
+
merge

reshape(
  merge(df,
    expand.grid(
      SEZ = unique(df$SEZ),
      Class = 1:7
    ),
    all = TRUE
  ),
  direction = "wide",
  idvar = "SEZ",
  timevar = "Class"
)

给予

     SEZ Val.1 Val.2 Val.3 Val.4 Val.5 Val.6 Val.7
1  1_1_1     2    NA    NA    NA     2    NA    NA
8  1_1_2    NA    NA    NA    NA     2    NA    NA
15 1_1_3     1    NA    NA    NA     2    NA    NA
22 1_1_4     1    NA    NA    NA    NA    NA    NA
29 1_1_5    NA     1    NA    NA    NA    NA    NA
36 1_2_1     2    NA    NA    NA     2    NA    NA

0
投票

当“值”列包含整数时会发生什么?

我尝试将@akran解决方案(上面发布的)应用于此表(偶然在“值”列中使用字符串而不是整数

数据

"1_1_4", "1_1_5", "1_2_1", "1_2_1"), Class = c(1L, 5L, 5L, 1L, 
5L, 1L, 2L, 1L, 5L), Val = c(2L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 
2L)), row.names = c(NA, -9L), class = "data.frame")

运行此命令会导致错误:

xtabs(Val ~ SEZ + Class, df1)

我们需要将输出列“Val”转换为数字,然后将其返回到文本。 此脚本完成工作(R 版本 4.3.1 (2023-06-16)dplyr 1.1.2):

# create list to translate
list_mapTclass <- seq(1:length(unique(df1$Val)))
print(length(list_mapTclass))
names(list_mapTclass) <-unique(df1$Val)


df1$idxTClass <- unlist(sapply(df1$Val, function(x) list_mapTclass[[x]] ))


wide_df_matrix <-xtabs(idxTClass ~ SEZ + idxTClass, df1)

#print(list_mapTclassInverted[1:3])
#--- add subid
wide_df0 <- as.data.frame.matrix( wide_df_matrix) %>% 
  setNames(paste0('col_', names(.))) #%>%


# reconvert values into the therapyclass content

# inverted list:

list_mapTclassInverted <- as.list(setNames(names(list_mapTclass), list_mapTclass))
list_mapTclassInverted[['0']] <- 'Unknown'


# Next piece of code is to go through the full table and convert all the integers into their text
### VERY USEFUL! (Thanks to: @Martin Morgan - https://stackoverflow.com/questions/7547597/dictionary-style-replace-multiple-items )
wide_df0[] <- list_mapTclassInverted[unlist(wide_df0)]

## convert to a dataframe

wide_df0$SEZ <- row.names(wide_df0) 
row.names(wide_df0) <- NULL

我会写另一篇关于这个问题的文章,以防这篇文章与问题完全匹配。 希望这可以帮助! 有时在 R 基础上做事情很耗时,但正如问题中提到的,当您必须使用没有更新的技术并且您不是 IT 管理员时,没有其他方法(特别是如果您必须在明天之前交付!)。

© www.soinside.com 2019 - 2024. All rights reserved.