Pandas每隔n行

224

Dataframe.resample()仅适用于时间序列数据。我找不到从非时间序列数据中获取每个第n行的方法。哪种方法最好?

7个回答

392

我会使用iloc,它可以基于整数位置和遵循Python正常语法来获取行/列切片。如果您想要每5行:

df.iloc[::5, :]

98
对于那些可能想要每隔五行选择一次的人,但是从第二行开始,代码应该是 df.iloc[1::5, :] - Little Bobby Tables
61
可以省略列部分:df.iloc[::5] - joctee
2
你如何从后面包含它? - WJA
1
如何使其不包括第0行? - Raksha
2
@banderlog013 不,那很直观 - 只需要 df.iloc[::3] 即可。你想要的(“直观上”),是在选择中第一行不是数据帧中的第一行。很容易看出,对于任何给定的 N(“给我以自然计数的第N行开始的N行”),索引是 df.iloc[(N-1)::N]。然而,这种行为很少需要... - Lodinn
显示剩余4条评论

55

虽然@chrisb的被接受的答案回答了问题,但我想对它进行以下补充。

我用来获取第n个数据或删除第n行的简单方法如下:

df1 = df[df.index % 3 != 0]  # Excludes every 3rd row starting from 0
df2 = df[df.index % 3 == 0]  # Selects every 3rd raw starting from 0

这种基于算术的抽样方法可以使行选择变得更加复杂。

当然,前提是您有一个从0开始、按顺序排列的整数索引列。


11
这不是一个好答案,因为它有三个假设,这些假设经常不满足:(1)索引是数字的(2)索引从零开始(3)索引值是连续的……最后一个特别重要,因为你不能在不重置索引的情况下使用你建议的方法超过一次。 - Constantine
3
我明白你的观点。我会编辑答案,使假设更加明确。 - metastableB
2
@Constantine,不过相比其他解决方案,这样做会更快,因为你可以简单地添加索引。 - Readler

13

对于已接受的答案,有一种更简单的解决方案,它涉及直接调用 df.__getitem__

df = pd.DataFrame('x', index=range(5), columns=list('abc'))
df

   a  b  c
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x
4  x  x  x
例如,要每2行获取一次,可以执行以下操作。
df[::2]

   a  b  c
0  x  x  x
2  x  x  x
4  x  x  x

同时还有 GroupBy.first/GroupBy.head,可以在索引上进行分组:

df.index // 2
# Int64Index([0, 0, 1, 1, 2], dtype='int64')

df.groupby(df.index // 2).first()
# Alternatively,
# df.groupby(df.index // 2).head(1)

   a  b  c
0  x  x  x
1  x  x  x
2  x  x  x

该索引被步幅(在本例中为2)做整除操作。如果该索引不是数字,请执行以下操作

# df.groupby(np.arange(len(df)) // 2).first()
df.groupby(pd.RangeIndex(len(df)) // 2).first()

   a  b  c
0  x  x  x
1  x  x  x
2  x  x  x

8
reset_index()添加到metastableB的回答中,可以让您仅需要假设行是有序和连续的
df1 = df[df.reset_index().index % 3 != 0]  # Excludes every 3rd row starting from 0
df2 = df[df.reset_index().index % 3 == 0]  # Selects every 3rd row starting from 0

df.reset_index().index会创建一个从0开始递增1的索引,使你能够轻松使用模运算。


2

我有类似的需求,但我想要特定组中的第n个项目。这是我的解决方法。

groups = data.groupby(['group_key'])
selection = groups['index_col'].apply(lambda x: x % 3 == 0)
subset = data[selection]

0
df.drop(labels=df[df.index % 3 != 0].index, axis=0) #  every 3rd row (mod 3)

4
虽然这段代码可能回答了问题,但是包括解释它如何或为什么解决问题会真正有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释,并指出适用的限制和假设。 - ppwater

0
当我使用索引时,我想到的一个解决方案不可行(可能是多GB的.csv文件太大了,或者我错过了一些技巧,使我无法重新索引而不崩溃)。 逐行遍历并将第n行添加到新数据框中。
import pandas as pd
from csv import DictReader

def make_downsampled_df(filename, interval):    
    with open(filename, 'r') as read_obj:
        csv_dict_reader = DictReader(read_obj)
        column_names = csv_dict_reader.fieldnames
        df = pd.DataFrame(columns=column_names)
    
        for index, row in enumerate(csv_dict_reader):
            if index % interval == 0:
               print(str(row))
               df = df.append(row, ignore_index=True)

    return df

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接