r - 在数据框列表中,用前导零填充一个变量(最好使用 stringr)
问题描述
我正在处理数据框列表。在每个数据帧中,我想用前导零填充单个 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
解决方案
您可以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
}
您会看到该函数有两个参数,i
and y
(如果您喜欢,请选择其他名称,例如df
and width
),并且对于列表中的每个数据框,它都会修改第一列dfl[[i]][, 1] <- ...
。匿名函数的作用是应用于str_pad
每个数据帧的第一列
... <- str_pad(dfl[[i]][, 1], width = y, pad = "0")
但是您会看到我们没有将固定值传递给width
参数,而是y
.
回到Map
. Map
现在适用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)
推荐阅读
- django - Django rest_framework 过滤器中的包含方法是什么
- c# - Selenium webdriver 测试 100% 在本地通过,在 VSTS 服务器上 100% 失败
- python-3.x - 使用 Tkinter 定义文件列表以用于分析。很难全局访问变量。(Python 3)
- swift - Swift SearchBar 无法过滤数据
- android - 使用 Android 和 LibGDX 编译游戏的问题
- python - 如何将字符串附加到数据框中的每个后续行?
- c++ - 使用 VS2017 构建 GLUI 时出现 C2252 错误?
- android - 如何在不更改其他布局的情况下更改 RecyclerView 中的单个项目
- php - 使用 $_SESSION php 的多级导航栏
- asp.net - Asp.net Webforms:为 typeform 创建 webhook 接收器