在R中根据列中的一个值填充数据框。

huangapple go评论109阅读模式
英文:

Fill across a data frame based on a value in a column in R

问题

我想要填充在y中指定的列数中m0中的值。期望的结果是:

y m0 m1 m2 mn
1 5 5 NA NA
2 15 15 15 NA
3 25 25 25 25

感谢任何指导!

英文:

I have a data frame as below:

y m0 m1 m2 mn
1 5 NA NA NA
2 15 NA NA NA
3 25 NA NA NA

I would like to fill the value in m0 across the number of columns specified in y. Desired result is:

y m0 m1 m2 mn
1 5 5 NA NA
2 15 15 15 NA
3 25 25 25 25

Appreciate any guidance!

答案1

得分: 1

你可以首先将你的数据转换成“长”格式,然后在NA的计数在y内时,用first值替换NA

library(tidyverse)

df %>%
  pivot_longer(-y) %>%
  mutate(value = ifelse(is.na(value) & cumsum(is.na(value)) <= y, first(value), value),
         .by = y) %>%
  pivot_wider()

#> # A tibble: 3 × 5
#>       y    m0    m1    m2    mn
#>   <int> <int> <int> <int> <int>
#> 1     1     5     5    NA    NA
#> 2     2    15    15    15    NA
#> 3     3    25    25    25    25

请注意,这是R语言中的代码示例,用于将数据从宽格式转换为长格式,然后在特定条件下替换缺失值。

英文:

You can first transform your data to a "long" format, then replace NA with the first value when the count of NA is within y.

library(tidyverse)

df %&gt;% 
  pivot_longer(-y) %&gt;% 
  mutate(value = ifelse(is.na(value) &amp; cumsum(is.na(value)) &lt;= y, first(value), value),
         .by = y) %&gt;% 
  pivot_wider()

#&gt; # A tibble: 3 &#215; 5
#&gt;       y    m0    m1    m2    mn
#&gt;   &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;int&gt;
#&gt; 1     1     5     5    NA    NA
#&gt; 2     2    15    15    15    NA
#&gt; 3     3    25    25    25    25

答案2

得分: 1

A 基本 R 方法使用 sapplycolbeg 定义了第一个需要替换 NA 的列。可以硬编码,但我怀疑它应该可调整为真实数据。

colbeg <- 3

data.frame(t(sapply(seq_along(df$y), \(x){
  df[x,colbeg:(colbeg - 1 + df$y[x])] <- df$m0[x]; df[x,]})))
  y m0 m1 m2 mn
1 1  5  5 NA NA
2 2 15 15 15 NA
3 3 25 25 25 25
英文:

A base R approach using sapply. colbeg defines the first column where NA has to be replaced. Can be hard coded but I suspect that it should be adjustable for the real data.

colbeg &lt;- 3

data.frame(t(sapply(seq_along(df$y), \(x){
  df[x,colbeg:(colbeg - 1 + df$y[x])] &lt;- df$m0[x]; df[x,]})))
  y m0 m1 m2 mn
1 1  5  5 NA NA
2 2 15 15 15 NA
3 3 25 25 25 25

答案3

得分: 0

Base R:

```r
lapply(setNames(0:2, paste0("m", 0:2 + 1)), function(z) if (z < 1) quux$m0 else c(rep(NA, z), tail(quux$m0, n = -z))) |
  as.data.frame()
#   m1 m2 m3
# 1  5 NA NA
# 2 15 15 NA
# 3 25 25 25

You can either replace the columns or cbind them.

quux[,0:2 + 3] <- lapply(setNames(0:2, paste0("m", 0:2 + 1)), function(z) if (z < 1) quux$m0 else c(rep(NA, z), tail(quux$m0, n = -z))) |
  as.data.frame()

quux <- cbind(
  quux[,1:2],
  lapply(setNames(0:2, paste0("m", 0:2 + 1)), function(z) if (z < 1) quux$m0 else c(rep(NA, z), tail(quux$m0, n = -z)))
)

(I'm consistently using 0:2 and offsets to show how things would be changed for an arbitrary number of columns.)


<details>
<summary>英文:</summary>

Base R:

```r
lapply(setNames(0:2, paste0(&quot;m&quot;, 0:2 + 1)), function(z) if (z &lt; 1) quux$m0 else c(rep(NA, z), tail(quux$m0, n = -z))) |&gt;
  as.data.frame()
#   m1 m2 m3
# 1  5 NA NA
# 2 15 15 NA
# 3 25 25 25

You can either replace the columns or cbind them.

quux[,0:2 + 3] &lt;- lapply(setNames(0:2, paste0(&quot;m&quot;, 0:2 + 1)), function(z) if (z &lt; 1) quux$m0 else c(rep(NA, z), tail(quux$m0, n = -z))) |&gt;
  as.data.frame()

quux &lt;- cbind(
  quux[,1:2],
  lapply(setNames(0:2, paste0(&quot;m&quot;, 0:2 + 1)), function(z) if (z &lt; 1) quux$m0 else c(rep(NA, z), tail(quux$m0, n = -z)))
)

(I'm consistently using 0:2 and offsets to show how things would be changed for an arbitrary number of columns.)

huangapple
  • 本文由 发表于 2023年6月22日 20:41:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76532031.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定