关于python 3.x:使用pandas从csv中删除特定行

delete specific rows from csv using pandas

我有一个如下所示格式的csv文件:enter image description here

我编写了以下代码来读取文件并随机删除转向值为0的行。我只想保留转向值为0的行的10%。

1
2
df = pd.read_csv(filename, header=None, names = ["center","left","right","steering","throttle", 'break', 'speed'])
df = df.drop(df.query('steering==0').sample(frac=0.90).index)

但是,我得到以下错误:

df = df.drop(df.query('steering==0').sample(frac=0.90).index)

locs = rs.choice(axis_length, size=n, replace=replace, p=weights)

File"mtrand.pyx", line 1104, in mtrand.RandomState.choice
(numpy/random/mtrand/mtrand.c:17062)

ValueError: a must be greater than 0

你们能帮我吗?


用@andrewu reece的代码构建的示例数据帧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
In [9]: df
Out[9]:
           center         left         right  steering  throttle  brake
0   center_54.jpg  left_75.jpg  right_39.jpg         1         0      0
1   center_20.jpg  left_81.jpg  right_49.jpg         3         1      1
2   center_34.jpg  left_96.jpg  right_11.jpg         0         4      2
3   center_98.jpg  left_87.jpg  right_34.jpg         0         0      0
4   center_67.jpg  left_12.jpg  right_28.jpg         1         1      0
5   center_11.jpg  left_25.jpg  right_94.jpg         2         1      0
6   center_66.jpg  left_27.jpg  right_52.jpg         1         3      3
7   center_18.jpg  left_50.jpg  right_17.jpg         0         0      4
8   center_60.jpg  left_25.jpg  right_28.jpg         2         4      1
9   center_98.jpg  left_97.jpg  right_55.jpg         3         3      0
..            ...          ...           ...       ...       ...    ...
90  center_31.jpg  left_90.jpg  right_43.jpg         0         1      0
91  center_29.jpg   left_7.jpg  right_30.jpg         3         0      0
92  center_37.jpg  left_10.jpg  right_15.jpg         1         0      0
93  center_18.jpg   left_1.jpg  right_83.jpg         3         1      1
94  center_96.jpg  left_20.jpg  right_56.jpg         3         0      0
95  center_37.jpg  left_40.jpg  right_38.jpg         0         3      1
96  center_73.jpg  left_86.jpg  right_71.jpg         0         1      0
97  center_85.jpg  left_31.jpg   right_0.jpg         3         0      4
98  center_34.jpg  left_52.jpg  right_40.jpg         0         0      2
99  center_91.jpg  left_46.jpg  right_17.jpg         0         0      0

[100 rows x 6 columns]

In [10]: df.steering.value_counts()
Out[10]:
0    43    # NOTE: 43 zeros
1    18
2    15
4    12
3    12
Name: steering, dtype: int64

In [11]: df.shape
Out[11]: (100, 6)

您的解决方案(不变):

1
2
3
4
5
6
7
8
9
10
11
12
13
In [12]: df = df.drop(df.query('steering==0').sample(frac=0.90).index)

In [13]: df.steering.value_counts()
Out[13]:
1    18
2    15
4    12
3    12
0     4        # NOTE: 4 zeros (~10% from 43)
Name: steering, dtype: int64

In [14]: df.shape
Out[14]: (61, 6)

注意:确保steering列具有数字数据类型!如果它是一个字符串(对象),那么您需要按如下方式更改代码:

1
2
df = df.drop(df.query('steering=="0"').sample(frac=0.90).index)
#  NOTE:                         ^ ^

之后,您可以将修改(缩小)的数据帧保存为csv:

1
df.to_csv('/path/to/filename.csv', index=False)


这里有一个单行方法,使用concat()sample()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
import pandas as pd

# first, some sample data

# generate filename fields
positions = ['center','left','right']
N = 100
fnames = ['{}_{}.jpg'.format(loc, np.random.randint(100)) for loc in np.repeat(positions, N)]
df = pd.DataFrame(np.array(fnames).reshape(3,100).T, columns=positions)

# generate numeric fields
values = [0,1,2,3,4]
probas = [.5,.2,.1,.1,.1]
df['steering'] = np.random.choice(values, p=probas, size=N)
df['throttle'] = np.random.choice(values, p=probas, size=N)
df['brake'] = np.random.choice(values, p=probas, size=N)

print(df.shape)
(100,3)

示例输出的前几行:

1
2
3
4
5
6
7
8
df.head()
           center         left         right  steering  throttle  brake
0   center_72.jpg  left_26.jpg  right_59.jpg         3         3      0
1   center_75.jpg  left_68.jpg  right_26.jpg         0         0      2
2   center_29.jpg   left_8.jpg  right_88.jpg         0         1      0
3   center_22.jpg  left_26.jpg  right_23.jpg         1         0      0
4   center_88.jpg   left_0.jpg  right_56.jpg         4         1      0
5   center_93.jpg  left_18.jpg  right_15.jpg         0         0      0

现在,除去使用steering==0的行的10%以外,其余行都将被删除:

1
2
newdf = pd.concat([df.loc[df.steering!=0],
                   df.loc[df.steering==0].sample(frac=0.1)])

在本例中使用的概率权重中,您将看到newdf中剩余的50-60个条目,剩余的大约5个steering==0个条目。


steering上使用一个蒙版和一个随机数应该可以工作:

1
df = df[(df.steering != 0) | (np.random.rand(len(df)) < 0.1)]

这确实会产生一些额外的随机值,但是它很好而且紧凑。

编辑:也就是说,我尝试了您的示例代码,它也工作得很好。我猜错误是由于您的df.query()语句返回空数据帧,这可能意味着"sample"列不包含任何零,或者该列被读取为字符串而不是数字。在运行上述代码段之前,请尝试将列转换为整数。