【问题标题】:Split dataframe by row number follow by every specific row number count to create multiple data frames按行号拆分数据帧,然后是每个特定的行号计数以创建多个数据帧
【发布时间】:2021-10-26 16:58:09
【问题描述】:

例如,我想拆分一个包含 1,079,882 行的数据帧,从 1,048,575 开始,然后是下一个 1,048,575

我试图做这样的事情

x<-split(df, rep(1:1048575, 1048575))
list2env(x,envir = .GlobalEnv)

但它不起作用。根据我想要做的,我应该得到 2 个数据框。如果我的数据框有 2,097,160 我应该有三个,前两个有 1,048,575 行,第三个有 5 行。

【问题讨论】:

  • 你完全正确。那不应该在那里。
  • 看来这是stackoverflow.com/q/7060272/3358272的骗子; @user35131,这对你也有用吗?
  • 我正在尝试这样做,但它不起作用。
  • rep函数接受各种参数,包括times=、each=和length.out=;您的使用默认为 times=,这意味着您想要 1:1048575(1e6 长),每个值重复 1e6 次......所以您将 1,079,882 行帧由 1e6 * 1e6(1e12)数字分割,这正在爆炸您的数据。
  • 仅供参考,“但它不起作用” 不是很清楚;虽然我认为我们已经弄清楚它为什么不起作用,但在未来请证实这样的陈述。

标签: r split


【解决方案1】:

我将演示小于 1e6 行的内容:mtcars。

假设您希望将框架拆分为每行不超过 10 行。由于它有 32 行,这意味着我们应该有 3 帧,每帧 10 行,一帧 2 行。

我们将使用%/% 整数(下限)除法运算符。需要注意的是,我们需要从0开始,而不是R默认的1,所以我们要减去1。

(seq_len(nrow(mtcars)) - 1) %/% 10
#  [1] 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3

从这里开始,就分开吧:

out <- split(mtcars, (seq_len(nrow(mtcars)) - 1) %/% 10)
sapply(out, nrow)
#  0  1  2  3 
# 10 10 10  2 

out
# $`0`
#                    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4         21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# Datsun 710        22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
# Valiant           18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
# Duster 360        14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
# Merc 240D         24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
# Merc 230          22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
# Merc 280          19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
# $`1`
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
# Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
# Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
# Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
# Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
# Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
# Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
# Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
# Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
# Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# $`2`
#                   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Toyota Corona    21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
# Dodge Challenger 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
# AMC Javelin      15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
# Camaro Z28       13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
# Pontiac Firebird 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
# Fiat X1-9        27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
# Porsche 914-2    26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
# Lotus Europa     30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
# Ford Pantera L   15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
# Ferrari Dino     19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
# $`3`
#                mpg cyl disp  hp drat   wt qsec vs am gear carb
# Maserati Bora 15.0   8  301 335 3.54 3.57 14.6  0  1    5    8
# Volvo 142E    21.4   4  121 109 4.11 2.78 18.6  1  1    4    2

这种技术有几个优点:

  • 它的内存效率很高,因为seq_len(.) 仅在您的框架有行数时才算高;它不会尝试做rep(highnumber, highnumber),当你有1e6左右的行时,这通常会超过R的内存;
  • 它直接控制哪一行进入哪个组
  • 如果您希望您的名字以 1 为基础,则添加一个,如 (seq_len(.)-1) %/% 10 + 1;如果您希望名称是其他名称,names(out) &lt;- c(...) 也可以使用

另一点:从某种意义上说,将其保存在 list 中而不是将其转移到全局环境中通常要好得多:一旦您对 lapply 和朋友感到更加舒适,它就会使您的环境保持整洁,允许您可以在一个动作中为所有帧重复一项任务(而不是为每个命名变量复制/粘贴),并且是处理数据的一种非常“规范”的方法(在 R 中)。见https://stackoverflow.com/a/24376207/3358227。

【讨论】:

  • 好的,成功了。忽略之前的消息。谢谢。
【解决方案2】:

你可以这样做:

  1. 定义行块
  2. 定义行的长度
  3. 定义数据框中的块数量
  4. 按定义的数量分割数据帧
chunk <- 1048575
n <- nrow(df)
r  <- rep(1:ceiling(n/chunk),each=chunk)[1:n]
d <- split(df,r)
d

【讨论】:

  • 我在 split.default(df, r) 中遇到错误:第一个参数必须是向量
  • 用 mtcasrs 数据集试试:它应该可以工作:chunk &lt;- 10 n &lt;- nrow(mtcars) r &lt;- rep(1:ceiling(n/chunk),each=chunk)[1:n] d &lt;- split(mtcars,r) d
  • 那是一个不同的数据集。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 2012-08-13
  • 1970-01-01
  • 2013-11-16
相关资源
最近更新 更多