在数据框列表中,用前导零填充一个变量(最好使用 stringr)

Posted

技术标签:

【中文标题】在数据框列表中,用前导零填充一个变量(最好使用 stringr)【英文标题】:In a list of data frames, pad one variable with leading zeros (ideally w/ stringr) 【发布时间】:2019-02-14 22:00:45 【问题描述】:

我正在处理数据框列表。在每个数据帧中,我想用前导零填充单个 ID 变量。 ID 变量是字符向量,并且始终是数据框中的第一个变量。然而,在每个数据帧中,ID 变量具有不同的长度。例如:

df1_id 的范围是 1:20,因此我需要最多填充一个零, df2_id 的范围为 1:100,因此我需要最多填充两个零, 等等

我的问题是,如何在不必为列表中的每个数据帧编写一行代码的情况下填充每个数据帧。

如上所述,我可以通过在每个数据帧上分别使用 str_pad 函数来解决这个问题。例如,看下面的代码:

#Load stringr package
library(stringr)

#Create sample data frames
df1 <- data.frame("x" = as.character(1:20), "y" = rnorm(20, 10, 1), 
stringsAsFactors = FALSE)

df2 <- data.frame("v" = as.character(1:100), "y" = rnorm(100, 10, 1), 
stringsAsFactors = FALSE)

df3 <- data.frame("z" = as.character(1:1000), "y" = rnorm(1000, 10, 1), 
stringsAsFactors = FALSE)

#Combine data fames into list
dfl <- list(df1, df2, df3)

#Pad ID variables with leading zeros
dfl[[1]]$x <- str_pad(dfl[[1]]$x, width = 2, pad = "0")
dfl[[2]]$v <- str_pad(dfl[[2]]$v, width = 3, pad = "0")
dfl[[3]]$z <- str_pad(dfl[[3]]$z, width = 4, pad = "0")

虽然此解决方案对于简短列表的效果相对较好,但随着数据帧数量的增加,它会变得有点笨拙。

如果有一种方法可以将某种“序列”向量嵌入到 str_pad 函数的宽度参数中,我会很高兴。像这样的:

dfl <- lapply(dfl, function(x) x[,1] <- str_pad(x[,1], width = SEQ, pad = 
"0"))

其中 SEQ 是可变长度的向量。使用上面的例子,它看起来像:

seq <- c(2,3,4)

提前致谢,如果您有任何问题,请告诉我。

~kj

【问题讨论】:

如果你不想使用额外的包,你可以试试formatC而不是str_pad 如果该答案解决了您的问题,请考虑accept它。 成功了,谢谢!抱歉耽搁了。我花了几天时间才找到时间回到这个问题!干杯,伙计! 【参考方案1】:

您可以在此处使用Map,它旨在将函数“应用于每个... 参数的第一个元素、第二个元素、第三个元素”,有关详细信息,请参阅?mapply

library(stringr)
vec <- c(2,3,4) # this is the vector of 'widths', don't name it seq

Map(function(i, y) 
  dfl[[i]][, 1] <- str_pad(dfl[[i]][, 1], width = y, pad = "0")
  dfl[[i]] # this gets returned
, 
# you iterate over these two vectors in parallel
i = 1:length(dfl), 
y = vec) 

输出

#[[1]]
#   x         y
#1 01  9.373546
#2 02 10.183643
#3 03  9.164371
#
#[[2]]
#    v         y
#1 001 11.595281
#2 002 10.329508
#3 003  9.179532
#4 004 10.487429
#
#[[3]]
#     z         y
#1 0001 10.738325
#2 0002 10.575781
#3 0003  9.694612
#4 0004 11.511781
#5 0005 10.389843

解释

我们传递给Map 的函数是一个匿名函数,您在问题中或多或少地提供了它:

function(i, y) 
  dfl[[i]][, 1] <- str_pad(dfl[[i]][, 1], width = y, pad = "0")
  dfl[[i]] # this gets returned

您会看到该函数有两个参数,iy(如果您愿意,可以选择其他名称,例如 dfwidth),并且对于列表中的每个数据框,它都会修改第一列 @987654332 @ .匿名函数的作用是将str_pad 应用于每个数据帧的第一列

... <- str_pad(dfl[[i]][, 1], width = y, pad = "0")

但是您看到我们没有将固定值传递给width 参数,而是y

回到MapMap 现在将str_pad 应用于第一个数据帧,参数width = 2,将str_pad 应用于第二个数据帧,参数width = 3 并且-您可能猜到了-它将str_pad 应用于第三个数据帧在您的列表中,带有参数width = 4

参数在代码的最后两行中指定为

i = 1:length(dfl), 
y = vec) 

我希望这会有所帮助。


数据

(考虑下次创建一个最小示例,因为数据帧的行数与问题无关)

set.seed(1)
df1 <- data.frame("x" = as.character(1:3), "y" = rnorm(3, 10, 1), 
                  stringsAsFactors = FALSE)

df2 <- data.frame("v" = as.character(1:4), "y" = rnorm(4, 10, 1), 
                  stringsAsFactors = FALSE)

df3 <- data.frame("z" = as.character(1:5), "y" = rnorm(5, 10, 1), 
                  stringsAsFactors = FALSE)

#Combine data fames into list
dfl <- list(df1, df2, df3)

【讨论】:

以上是关于在数据框列表中,用前导零填充一个变量(最好使用 stringr)的主要内容,如果未能解决你的问题,请参考以下文章

如何用前导零填充数组?

在 XSLT 1.0 中使用前导零填充数字

用前导零填充字符串,使其在 SQL Server 2008 中的长度为 3 个字符

用前导零填充字符字段

将前导零添加到 Spark 数据框中的列 [重复]

Python 在时间序列数据框中填充零并保留现有值