Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 取消列出/取消列出列到多个列中_R_List_Unnest - Fatal编程技术网

R 取消列出/取消列出列到多个列中

R 取消列出/取消列出列到多个列中,r,list,unnest,R,List,Unnest,我知道在数据帧中取消列表列的测试的问题已经被提出并回答了多次。然而,这里是潜在的237。这类问题 我有以下数据: set.seed(666) dat <- data.frame(sysRespNum = c(1,2,3,4,5,6), product1 = sqrt(rnorm(6, 20, 5)^2), product2 = sqrt(rnorm(6, 20, 5)^2),

我知道在数据帧中取消列表列的测试的问题已经被提出并回答了多次。然而,这里是潜在的237。这类问题

我有以下数据:

set.seed(666)
dat <- data.frame(sysRespNum = c(1,2,3,4,5,6),
                  product1   = sqrt(rnorm(6, 20, 5)^2),
                  product2   = sqrt(rnorm(6, 20, 5)^2),
                  product3   = sqrt(rnorm(6, 20, 5)^2))
现在,我想计算每个产品在所有产品总和中的比例,因此我想计算
product1/sum(我的三个产品)
,然后计算产品2和3的比例。所以我期待有三个新专栏

我尝试了以下方法:

library(tidyverse)    
dat %>%
  mutate(sum_Product = apply(across(-sysRespNum), 1, function(x) list(sum_Product = x/sum(x))))
(旁白:是否有一种更直接的方法可以直接对其进行变异,而无需创建列表。我现在可以先创建一个求和列,然后再进行简单的变异和交叉。但我想知道是否可以在不创建临时求和列的情况下实现计算)

现在我的问题是很难取消测试
sum\u Product
list列
unnest\u-wide
不起作用,
sum\u-Product
列仍然是一个列表

所以对我来说唯一有效的就是

  • 遵循此解决方案:
  • 更改上面的“我的代码”,并将
    列表
    部分替换为
    数据框
完整代码:

dat %>%
  mutate(sum_Product = apply(across(-sysRespNum), 1, function(x) data.frame(sum_Product = x/sum(x)))) %>%
  unnest(cols = everything()) %>%
  mutate(product = rep(1:3, nrow(.)/3)) %>%
  pivot_wider(values_from = sum_Product,
              names_from = product,
              names_prefix = "share_product")
这给出了正确的结果:

# A tibble: 6 x 7
  sysRespNum product1 product2 product3 share_product1 share_product2
       <dbl>    <dbl>    <dbl>    <dbl>          <dbl>          <dbl>
1          1    23.8      13.5     24.3          0.386          0.219
2          2    30.1      16.0     11.4          0.523          0.278
3          3    18.2      11.0     20.7          0.365          0.221
4          4    30.1      19.8     19.6          0.433          0.285
5          5     8.92     30.8     24.3          0.139          0.481
6          6    23.8      11.1     21.7          0.420          0.197
# … with 1 more variable: share_product3 <dbl>
#一个tible:6 x 7
sysRespNum product1 product2 product3 share\U product1 share\U product2
1          1    23.8      13.5     24.3          0.386          0.219
2          2    30.1      16.0     11.4          0.523          0.278
3          3    18.2      11.0     20.7          0.365          0.221
4          4    30.1      19.8     19.6          0.433          0.285
5          5     8.92     30.8     24.3          0.139          0.481
6          6    23.8      11.1     21.7          0.420          0.197
#…还有1个变量:share_product3
然而,感觉没有必要把所有的东西都卸下,然后用pivot_进行重塑


因此,a)是否有一种更优雅的方法来计算我的共享变量,b)是否有一种更优雅/更短/更不冗长的方法来将列表列重塑为多个向量列?

更容易做到这一点
rowSums
,即在以关键字“product”开头的列上,将“product1”除以
rowSums
。与使用跨
c_
rowwise
不同,这是矢量化的,应该也很快

library(dplyr)
dat %>%
    mutate(sum_product = product1/rowSums(select(., starts_with('product'))))
注意:
base R
代码(
apply
)和跨
的tidyverse选项混合使用,这似乎不是最佳方式


如果我们需要对所有“产品”列执行此操作,请首先使用
mutate
创建一个
sum
列,然后在以“产品”开头的列上使用
cross
将该列除以“sum\u col”

dat %>%
     mutate(Sum_col = rowSums(select(., starts_with('product'))),
           across(starts_with('product'),
        ~ ./Sum_col, .names = '{.col}_sum_product')) %>%
     select(-Sum_col)
-输出

#ysRespNum  product1 product2 product3 product1_sum_product product2_sum_product product3_sum_product
#1          1 23.766555 13.46907 24.32327            0.3860783            0.2187998            0.3951219
#2          2 30.071773 15.98740 11.39922            0.5233660            0.2782431            0.1983909
#3          3 18.224328 11.03880 20.67063            0.3649701            0.2210688            0.4139610
#4          4 30.140839 19.78984 19.62087            0.4333597            0.2845348            0.2821054
#5          5  8.915628 30.75021 24.29150            0.1393996            0.4807925            0.3798079
#6          6 23.791981 11.14885 21.72450            0.4198684            0.1967490            0.3833826

或使用
base R

nm1 <- startsWith(names(dat), 'product')
dat[paste0('sum_product', seq_along(nm1))] <- dat[nm1]/rowSums(dat[nm1])

nm1更容易做到这一点
rowSums
,即在以关键字“product”开头的列上将“product1”除以
rowSums
。与使用跨
c_
rowwise
不同,这是矢量化的,应该也很快

library(dplyr)
dat %>%
    mutate(sum_product = product1/rowSums(select(., starts_with('product'))))
注意:
base R
代码(
apply
)和跨
的tidyverse选项混合使用,这似乎不是最佳方式


如果我们需要对所有“产品”列执行此操作,请首先使用
mutate
创建一个
sum
列,然后在以“产品”开头的列上使用
cross
将该列除以“sum\u col”

dat %>%
     mutate(Sum_col = rowSums(select(., starts_with('product'))),
           across(starts_with('product'),
        ~ ./Sum_col, .names = '{.col}_sum_product')) %>%
     select(-Sum_col)
-输出

#ysRespNum  product1 product2 product3 product1_sum_product product2_sum_product product3_sum_product
#1          1 23.766555 13.46907 24.32327            0.3860783            0.2187998            0.3951219
#2          2 30.071773 15.98740 11.39922            0.5233660            0.2782431            0.1983909
#3          3 18.224328 11.03880 20.67063            0.3649701            0.2210688            0.4139610
#4          4 30.140839 19.78984 19.62087            0.4333597            0.2845348            0.2821054
#5          5  8.915628 30.75021 24.29150            0.1393996            0.4807925            0.3798079
#6          6 23.791981 11.14885 21.72450            0.4198684            0.1967490            0.3833826

或使用
base R

nm1 <- startsWith(names(dat), 'product')
dat[paste0('sum_product', seq_along(nm1))] <- dat[nm1]/rowSums(dat[nm1])

nm1我想下面的基本R代码应该适合您

cbind(
  dat,
  setNames(dat[-1] / rowSums(dat[-1]), paste0("share_product", seq_along(dat[-1])))
)

  sysRespNum  product1 product2 product3 share_product1 share_product2
1          1 23.766555 13.46907 24.32327      0.3860783      0.2187998
2          2 30.071773 15.98740 11.39922      0.5233660      0.2782431
3          3 18.224328 11.03880 20.67063      0.3649701      0.2210688
4          4 30.140839 19.78984 19.62087      0.4333597      0.2845348
5          5  8.915628 30.75021 24.29150      0.1393996      0.4807925
6          6 23.791981 11.14885 21.72450      0.4198684      0.1967490
  share_product3
1      0.3951219
2      0.1983909
3      0.4139610
4      0.2821054
5      0.3798079
6      0.3833826

我想下面的基本R代码应该适合您

cbind(
  dat,
  setNames(dat[-1] / rowSums(dat[-1]), paste0("share_product", seq_along(dat[-1])))
)

  sysRespNum  product1 product2 product3 share_product1 share_product2
1          1 23.766555 13.46907 24.32327      0.3860783      0.2187998
2          2 30.071773 15.98740 11.39922      0.5233660      0.2782431
3          3 18.224328 11.03880 20.67063      0.3649701      0.2210688
4          4 30.140839 19.78984 19.62087      0.4333597      0.2845348
5          5  8.915628 30.75021 24.29150      0.1393996      0.4807925
6          6 23.791981 11.14885 21.72450      0.4198684      0.1967490
  share_product3
1      0.3951219
2      0.1983909
3      0.4139610
4      0.2821054
5      0.3798079
6      0.3833826
好的,老的,普通的

rdat <- dat[-1]
rdat <- rdat/rowSums(rdat)
colnames(rdat) <- paste0("share_", colnames(rdat))
cbind(dat, rdat)
好的,老的,普通的

rdat <- dat[-1]
rdat <- rdat/rowSums(rdat)
colnames(rdat) <- paste0("share_", colnames(rdat))
cbind(dat, rdat)

是的,但这只给了我产品1的份额,而不是产品2和3的份额。我希望避免硬编码这三种产品中的每一种,因为在现实生活中,我在不同的用例中有不同数量的产品列。否则,我通常同意行和比较快。@deschen也许更新有助于youThanks akrun。是的,也考虑过这个解决方案(即首先创建一个包含总和的临时列),但是如果没有这个步骤,有一个直接的方法(即在我的帖子中,我有点排除了这个临时总和选项),我会感到惊讶。@deschen创建一个临时列比执行
行总和
n timesYes更好,但这只给了我产品1的份额,而不是产品2和3的份额。我希望避免硬编码这三种产品中的每一种,因为在现实生活中,我在不同的用例中有不同数量的产品列。否则,我通常同意行和比较快。@deschen也许更新有助于youThanks akrun。是的,也考虑过这个解决方案(即首先创建一个包含总和的临时列),但是如果没有这个步骤,有一个直接的方法(即在我的帖子中,我有点排除了这个临时总和选项)。@deschen创建一个临时列比执行
rowSums
n次它不是tidyverse,但是
prop.table
应该做
vars它不是tidyverse,但是
prop.table
应该做
vars