将行转置为列,并使用N/A表示缺失值。

7
我有一个类似于这样的数据框:
NUM <- c("45", "45", "45", "45", "48", "50", "66", "66", "66", "68")
Type <- c("A", "F", "C", "B", "D", "A", "E", "C", "F", "D")
Points <- c(9.2,60.8,22.9,1012.7,18.7,11.1,67.2,63.1,16.7,58.4)

df1 <- data.frame(NUM,Type,Points)

df1:
+-----+------+--------+
| NUM | TYPE | Points |
+-----+------+--------+
|  45 | A    | 9.2    |
|  45 | F    | 60.8   |
|  45 | C    | 22.9   |
|  45 | B    | 1012.7 |
|  48 | D    | 18.7   |
|  50 | A    | 11.1   |
|  66 | E    | 67.2   |
|  66 | C    | 63.1   |
|  66 | F    | 16.7   |
|  65 | D    | 58.4   |
+-----+------+--------+

我正在尝试获得一种输出,该输出将类型列中的行转换为单独的列。
期望的输出:
+-----+----------+----------+----------+----------+----------+----------+
| NUM | Points.A | Points.B | Points.C | Points.D | Points.E | Points.F |
+-----+----------+----------+----------+----------+----------+----------+
|  45 | 9.2      | 1012.7   | 22.9     | N/A      | N/A      | 60.8     |
|  48 | N/A      | N/A      | N/A      | 18.7     | N/A      | N/A      |
|  50 | 11.1     | N/A      | N/A      | N/A      | N/A      | N/A      |
|  66 | N/A      | N/A      | 63.1     | N/A      | 67.2     | 16.7     |
|  65 | N/A      | N/A      | N/A      | N/A      | 58.4     | N/A      |
+-----+----------+----------+----------+----------+----------+----------+

我尝试使用melt(df1),但是做错了,因为行中的值是 NUM 值而不是点。请告诉我如何解决这个问题。

3
melt 可以使数据变得更长,dcast 可以使数据变得更宽(同时还能进行聚合操作)。 - A5C1D2H2I1M1N2O1R2T1
2
或者 library(tidyr) ; spread(df1, Type, Points) - David Arenburg
2个回答

11
你正在寻找一种基本的“长”到“宽”的重塑过程。
在 R 中,你可以使用臭名昭著的 reshape。对于这种类型的数据,语法非常简单:
reshape(df1, direction = "wide", idvar = "NUM", timevar = "Type")
#    NUM Points.A Points.F Points.C Points.B Points.D Points.E
# 1   45      9.2     60.8     22.9   1012.7       NA       NA
# 5   48       NA       NA       NA       NA     18.7       NA
# 6   50     11.1       NA       NA       NA       NA       NA
# 7   66       NA     16.7     63.1       NA       NA     67.2
# 10  68       NA       NA       NA       NA     58.4       NA

你也可以使用"tidyr"包,它有几个功能与reshape2类似但语法不同。在这种情况下,语法应为:

```{r} # Tidying data from wide to long format tidyr::gather(data, new_column_name, new_value_name, columns_to_gather)
# Tidying data from long to wide format tidyr::spread(data, key_column_name, value_column_name) ```
> library(tidyr)
> spread(df1, Type, Points)

1
非常好用!谢谢Ananda。我刚刚在我的数据集上实现了reshape和spread函数,看起来它们生成结果的时间基本相同。你知道哪个更有效吗? - Sharath
3
@Sharath,这取决于您的数据集大小。通常而言,使用" data.table"的开发版本会更加高效,因为它具有快速的融合和转换功能,并且超越了"reshape2"的能力。尽管如此,我通常不喜欢使用软件包的开发版本来提供答案... - A5C1D2H2I1M1N2O1R2T1

6
你可以尝试使用 dcast
library(reshape2)
dcast(df1, NUM~paste0('Points.',Type), value.var='Points')

或者您可以将数据转换为 data.table 并使用来自 data.table 的 dcast。这样会更快。

library(data.table)#v1.9.5+
dcast(setDT(df1), NUM~paste0('Points.',Type), value.var='Points')

1
运行得非常出色。在大型数据集上,dcast是否比spread更快? - Sharath
3
针对更大的数据集,我会将 'data.frame' 转换为 'data.table' 然后使用数据表中的 dcast 函数。这样做速度很快。 - akrun
1
谢谢您的建议。看起来Ananda也提出了同样的建议。我会将其转换为data.table,并在处理更大的数据集时使用dcast。 - Sharath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接