【问题标题】:Pandas: Sampling a DataFrame [duplicate]Pandas:对 DataFrame 进行采样 [重复]
【发布时间】:2012-08-24 19:51:05
【问题描述】:

我正在尝试使用 Pandas 读取一个相当大的 CSV 文件并将其分成两个随机块,其中一个是 10% 的数据,另一个是 90%。

这是我目前的尝试:

rows = data.index
row_count = len(rows)
random.shuffle(list(rows))

data.reindex(rows)

training_data = data[row_count // 10:]
testing_data = data[:row_count // 10]

由于某种原因,sklearn 在我尝试在 SVM 分类器中使用这些生成的 DataFrame 对象之一时抛出此错误:

IndexError: each subindex must be either a slice, an integer, Ellipsis, or newaxis

我认为我做错了。有没有更好的方法来做到这一点?

【问题讨论】:

  • 顺便说一句,这不会随机正确随机洗牌 - 问题是random.shuffle(list(rows))shuffle 改变了它所操作的数据,但是当你调用 list(rows) 时,你复制了一个 rows 的副本,它被改变然后被丢弃 - 底层的 pandas 系列,rows,没有改变。一种解决方案是调用rows = list(rows),然后调用random.shuffle(rows)data.reindex(rows)

标签: python partitioning pandas


【解决方案1】:

您使用的是什么版本的熊猫?对我来说,您的代码运行良好(我在 git master 上)。

另一种方法可能是:

In [117]: import pandas

In [118]: import random

In [119]: df = pandas.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

In [120]: rows = random.sample(df.index, 10)

In [121]: df_10 = df.ix[rows]

In [122]: df_90 = df.drop(rows)

较新的版本(从 0.16.1 开始)直接支持此功能: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sample.html

【讨论】:

  • 另一种方法是使用np.random.permuation
  • @WesMcKinney:我注意到np.random.permutation 会从DataFrame 中删除列名,因为np.random.permutation。 pandas 中是否有一种方法可以在保留列名的同时对数据框进行洗牌?
  • @hlin df.loc[np.random.permutation(df.index)] 将打乱数据帧并保留列名。
  • @Wouter Overmeire,我刚试过这个,看起来它现在可以正常工作,但它也给了我一个弃用警告。
  • random.sample() 如果样本长度过长会导致RuntimeError: maximum recursion depth exceeded while calling a Python object。推荐np.random.choice()
【解决方案2】:

我发现 NumPy 1.7.0 中的 np.random.choice() new 对此非常有效。

例如,您可以传递来自 DataFrame 的索引值和整数 10 来选择 10 个随机均匀采样的行。

rows = np.random.choice(df.index.values, 10)
sampled_df = df.ix[rows]

【讨论】:

  • 使用 ipython timeit 它需要一半的 random.sample 时间.. 太棒了
  • +1 用于使用 np.random.choice。另外,如果你有一个pd.Series 的概率prob,你可以从索引中选择:np.random.choice(prob.index.values, p=prob.values)
  • 如果您想在没有替换的情况下进行采样,请不要忘记指定 replace=False。否则,此方法可能会多次采样同一行。
  • 如果您想从 df 中抽取“A”列的 N 个唯一值而无需替换,我发现以下有用: rand_Nvals = np.random.choice(list(set(df .A)), N, 替换=假)
  • 在我的例子中,我想repeat 数据——即获取列表 ['a','b','c'] 并将此列表设为 3,000 长(而不是 3 长)。 random.sample 不允许结果大于输入 (ValueError: Sample larger than population) np.random.choice 允许结果大于输入。我可能描述的是与 OP 不同的问题(他专门说“样本”=小于总体),但是...
【解决方案3】:

0.16.1 版中的新功能:

sample_dataframe = your_dataframe.sample(n=how_many_rows_you_want)

文档在这里:http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.sample.html

【讨论】:

  • 获得 sample_dataframe 后,如何从 your_dataframe 中减去它?
  • @ChrisNielsen 您是在问这样可以进行交叉验证吗?如果是这样,我推荐scikit-learn.org/stable/modules/cross_validation.html,因为它直接为您提供所有训练和测试数据集(X_train、X_test、y_train、y_test)
【解决方案4】:

Pandas 0.16.1 有一个 sample 方法。

【讨论】:

  • 不错!但是你仍然需要加载内存中的所有数据,对吧?
  • 我是在内存中加载数据后做的。
【解决方案5】:

如果您使用的是 pandas.read_csv,则可以在加载数据时使用 skiprows 参数直接采样。这是我写的一篇短文 - https://nikolaygrozev.wordpress.com/2015/06/16/fast-and-simple-sampling-in-pandas-when-loading-data-from-files/

【讨论】:

  • 查看 itertools.islice
  • 这是问题的正确答案。
猜你喜欢
  • 2021-10-05
  • 1970-01-01
  • 2017-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-24
  • 2013-12-06
相关资源
最近更新 更多