我有一个csv文件,如下所示:
ID Class Status Species
1 Sands D Carex
1 Sands C Eupesu
1 Sands C Poapra
2 Limy D Carcra
2 Limy C Eupesu
2 Limy C Poapra
3 Limy D Poapra
3 Limy C Eupesu
3 Limy C Poapra
当Status
为D
且Species
为Carex或Carcra时,我想将Class
更改为Wet
以获取特定ID中的所有值。我想要的输出是:
ID Class Status Species
1 Wet D Carex
1 Wet C Eupesu
1 Wet C Poapra
2 Wet D Carcra
2 Wet C Eupesu
2 Wet C Poapra
3 Limy D Poapra
3 Limy C Eupesu
3 Limy C Poapra
答案 0 :(得分:3)
import pandas as pd
df = pd.read_table('data', sep='\s+')
mask = ((df['Status'] == 'D')
& df['Species'].isin(['Carex','Carcra']))
mask = mask.groupby(df['ID']).transform('any')
df.loc[mask, 'Class'] = 'Wet'
print(df)
产量
ID Class Status Species
0 1 Wet D Carex
1 1 Wet C Eupesu
2 1 Wet C Poapra
3 2 Wet D Carcra
4 2 Wet C Eupesu
5 2 Wet C Poapra
6 3 Limy D Poapra
7 3 Limy C Eupesu
8 3 Limy C Poapra
作业
df['mask'] = ((df['Status'] == 'D')
& df['Species'].isin(['Carex','Carcra']))
使df
看起来像这样:
In [166]: df
Out[166]:
ID Class Status Species mask
0 1 Sands D Carex True
1 1 Sands C Eupesu False
2 1 Sands C Poapra False
3 2 Limy D Carcra True
4 2 Limy C Eupesu False
5 2 Limy C Poapra False
6 3 Limy D Poapra False
7 3 Limy C Eupesu False
8 3 Limy C Poapra False
现在,(感谢DSM):
mask = ((df['Status'] == 'D')
& df['Species'].isin(['Carex','Carcra']))
mask = mask.groupby(df['ID']).transform('any')
mask
分组df['ID']
,如果原始True
中的任何值为True,则将mask
分配给该组的所有行,和False
否则。
In [168]: mask
Out[168]:
0 True
1 True
2 True
3 True
4 True
5 True
6 False
7 False
8 False
dtype: bool
df.loc
可用于从df
中选择行和列。
df.loc[mask]
选择mask
为True的行:
In [169]: df.loc[mask]
Out[169]:
ID Class Status Species mask
0 1 Sands D Carex True
1 1 Sands C Eupesu False
2 1 Sands C Poapra False
3 2 Limy D Carcra True
4 2 Limy C Eupesu False
5 2 Limy C Poapra False
df.loc[mask, 'Class']
进一步选择列Class
:
In [170]: df.loc[mask, 'Class']
Out[170]:
0 Sands
1 Sands
2 Sands
3 Limy
4 Limy
5 Limy
Name: Class, dtype: object
df.loc[mask]['Class'] = value
可能无法修改df
,因为df.loc[mask]
会返回副本。 (df[mask]['Class'] = value
)也是如此。使用[...]
两次被称为"链式索引"如果我们避免链式索引,就可以避免这个问题。
因此,不要使用[...]
两次,而是使用df.loc[mask, 'Class'] = 'Wet'
:
In [172]: df
Out[172]:
ID Class Status Species
0 1 Wet D Carex
1 1 Wet C Eupesu
2 1 Wet C Poapra
3 2 Wet D Carcra
4 2 Wet C Eupesu
5 2 Wet C Poapra
6 3 Limy D Poapra
7 3 Limy C Eupesu
8 3 Limy C Poapra
答案 1 :(得分:0)
您标记了pandas,因此我假设您可以将其作为数据框导入。
如果是这样,我认为您正在寻找类似的东西:
df[(df.Status=='D') & (df.Species=='CareX' | df.Species=='Carcra') & (df.ID== 1)]['Class'] = 'Wet'
答案 2 :(得分:0)
嗯,这个答案可能效率低下,因为它会将文件中的所有行都记录下来。为了仅编辑文件的那一部分,我稍后会查看并编辑此答案。但是现在,如果你有一个不超过的文件,我不知道,50mb ?,只需使用它。
lines = []
theID = 1
for line in open("file.csv", "r"):
row = line.split(",")
if row[2] == "D":
if row[3] == "Carex" or row[3] == "Carcra":
if theID == row[0]:
row[1] = "Wet"
lines.append(",".join(row))
open("file.csv", "w").writelines(lines)
请在运行之前请备份您的实际文件,因为它可能会弄乱整个事情。 (未测试)