如何分隔包含有序对列表的列?
How to separate a column that contains a lists of ordered pairs?
我有一个数据集 df
,其中第三列 new
的形式为
我想问一下如何从 new
创建 2 个新列,其中第一列包含每个列表中的第一个元素,第二列包含每个列表中的第二个元素。特别是,它看起来像
这可以通过遍历每一行的简单循环来完成。因为我的真实数据集包含超过 100.000 行,所以循环效率不高。能否请您详细说明一个有效的方法?
data("mtcars")
df <- mtcars[, 1:2]
df$new <- lapply(setNames(asplit(df[c('mpg', 'cyl')], 1), NULL), as.vector)
df$mpg <- 0
df$cyl <- 0
因为它是 vector
的 list
,我们可以用 do.call
来 rbind
它们,并用 setNames
[= 改变列名17=]
out <- setNames(do.call(rbind.data.frame, df$new), c('var1', 'var2'))
如果需要分配给'mpg','cyl'已经创建为'0'
df[c('mpg', 'cyl')] <- do.call(rbind, df$new)
这里是 data.table
选项,使用 transpose
setDT(df)[, setNames(transpose(new), c("mpg", "cyl"))]
这给出了
mpg cyl
1: 21 6
2: 21 6
3: 22.8 4
4: 21.4 6
5: 18.7 8
6: 18.1 6
7: 14.3 8
8: 24.4 4
9: 22.8 4
10: 19.2 6
11: 17.8 6
12: 16.4 8
13: 17.3 8
14: 15.2 8
15: 10.4 8
16: 10.4 8
17: 14.7 8
18: 32.4 4
19: 30.4 4
20: 33.9 4
21: 21.5 4
22: 15.5 8
23: 15.2 8
24: 13.3 8
25: 19.2 8
26: 27.3 4
27: 26 4
28: 30.4 4
29: 15.8 8
30: 19.7 6
31: 15 8
32: 21.4 4
mpg cyl
或
> setDT(df)[, c("mpg", "cyl") := (lapply(transpose(new), unlist))][]
mpg cyl new
1: 21.0 6 21, 6
2: 21.0 6 21, 6
3: 22.8 4 22.8, 4.0
4: 21.4 6 21.4, 6.0
5: 18.7 8 18.7, 8.0
6: 18.1 6 18.1, 6.0
7: 14.3 8 14.3, 8.0
8: 24.4 4 24.4, 4.0
9: 22.8 4 22.8, 4.0
10: 19.2 6 19.2, 6.0
11: 17.8 6 17.8, 6.0
12: 16.4 8 16.4, 8.0
13: 17.3 8 17.3, 8.0
14: 15.2 8 15.2, 8.0
15: 10.4 8 10.4, 8.0
16: 10.4 8 10.4, 8.0
17: 14.7 8 14.7, 8.0
18: 32.4 4 32.4, 4.0
19: 30.4 4 30.4, 4.0
20: 33.9 4 33.9, 4.0
21: 21.5 4 21.5, 4.0
22: 15.5 8 15.5, 8.0
23: 15.2 8 15.2, 8.0
24: 13.3 8 13.3, 8.0
25: 19.2 8 19.2, 8.0
26: 27.3 4 27.3, 4.0
27: 26.0 4 26, 4
28: 30.4 4 30.4, 4.0
29: 15.8 8 15.8, 8.0
30: 19.7 6 19.7, 6.0
31: 15.0 8 15, 8
32: 21.4 4 21.4, 4.0
mpg cyl new
一个简单的 dplyr
/tidyr
替代方案可以是
library(tidyverse)
unnest_wider(df, new)
# A tibble: 32 x 4
mpg cyl ...1 ...2
<dbl> <dbl> <dbl> <dbl>
1 0 0 21 6
2 0 0 21 6
3 0 0 22.8 4
4 0 0 21.4 6
5 0 0 18.7 8
6 0 0 18.1 6
7 0 0 14.3 8
8 0 0 24.4 4
9 0 0 22.8 4
10 0 0 19.2 6
# ... with 22 more rows
我有一个数据集 df
,其中第三列 new
的形式为
我想问一下如何从 new
创建 2 个新列,其中第一列包含每个列表中的第一个元素,第二列包含每个列表中的第二个元素。特别是,它看起来像
这可以通过遍历每一行的简单循环来完成。因为我的真实数据集包含超过 100.000 行,所以循环效率不高。能否请您详细说明一个有效的方法?
data("mtcars")
df <- mtcars[, 1:2]
df$new <- lapply(setNames(asplit(df[c('mpg', 'cyl')], 1), NULL), as.vector)
df$mpg <- 0
df$cyl <- 0
因为它是 vector
的 list
,我们可以用 do.call
来 rbind
它们,并用 setNames
[= 改变列名17=]
out <- setNames(do.call(rbind.data.frame, df$new), c('var1', 'var2'))
如果需要分配给'mpg','cyl'已经创建为'0'
df[c('mpg', 'cyl')] <- do.call(rbind, df$new)
这里是 data.table
选项,使用 transpose
setDT(df)[, setNames(transpose(new), c("mpg", "cyl"))]
这给出了
mpg cyl
1: 21 6
2: 21 6
3: 22.8 4
4: 21.4 6
5: 18.7 8
6: 18.1 6
7: 14.3 8
8: 24.4 4
9: 22.8 4
10: 19.2 6
11: 17.8 6
12: 16.4 8
13: 17.3 8
14: 15.2 8
15: 10.4 8
16: 10.4 8
17: 14.7 8
18: 32.4 4
19: 30.4 4
20: 33.9 4
21: 21.5 4
22: 15.5 8
23: 15.2 8
24: 13.3 8
25: 19.2 8
26: 27.3 4
27: 26 4
28: 30.4 4
29: 15.8 8
30: 19.7 6
31: 15 8
32: 21.4 4
mpg cyl
或
> setDT(df)[, c("mpg", "cyl") := (lapply(transpose(new), unlist))][]
mpg cyl new
1: 21.0 6 21, 6
2: 21.0 6 21, 6
3: 22.8 4 22.8, 4.0
4: 21.4 6 21.4, 6.0
5: 18.7 8 18.7, 8.0
6: 18.1 6 18.1, 6.0
7: 14.3 8 14.3, 8.0
8: 24.4 4 24.4, 4.0
9: 22.8 4 22.8, 4.0
10: 19.2 6 19.2, 6.0
11: 17.8 6 17.8, 6.0
12: 16.4 8 16.4, 8.0
13: 17.3 8 17.3, 8.0
14: 15.2 8 15.2, 8.0
15: 10.4 8 10.4, 8.0
16: 10.4 8 10.4, 8.0
17: 14.7 8 14.7, 8.0
18: 32.4 4 32.4, 4.0
19: 30.4 4 30.4, 4.0
20: 33.9 4 33.9, 4.0
21: 21.5 4 21.5, 4.0
22: 15.5 8 15.5, 8.0
23: 15.2 8 15.2, 8.0
24: 13.3 8 13.3, 8.0
25: 19.2 8 19.2, 8.0
26: 27.3 4 27.3, 4.0
27: 26.0 4 26, 4
28: 30.4 4 30.4, 4.0
29: 15.8 8 15.8, 8.0
30: 19.7 6 19.7, 6.0
31: 15.0 8 15, 8
32: 21.4 4 21.4, 4.0
mpg cyl new
一个简单的 dplyr
/tidyr
替代方案可以是
library(tidyverse)
unnest_wider(df, new)
# A tibble: 32 x 4
mpg cyl ...1 ...2
<dbl> <dbl> <dbl> <dbl>
1 0 0 21 6
2 0 0 21 6
3 0 0 22.8 4
4 0 0 21.4 6
5 0 0 18.7 8
6 0 0 18.1 6
7 0 0 14.3 8
8 0 0 24.4 4
9 0 0 22.8 4
10 0 0 19.2 6
# ... with 22 more rows