基于特定标准修改多行

2024-09-28 17:01:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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

StatusDSpecies是Carex或Carcra时,我想将特定ID中所有值的Class更改为Wet。我想要的输出是:

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

Tags: 文件csvidstatusclassspecieswetcarex
3条回答

您标记了pandas,所以我假设您可以将其作为数据帧导入。你知道吗

如果是的话,我想你在找这样的东西:

df[(df.Status=='D') & (df.Species=='CareX' | df.Species=='Carcra') & (df.ID== 1)]['Class'] = 'Wet'

好吧,这个答案可能效率很低,因为它需要将文件中的所有行存储到内存中。为了只编辑文件的那一部分,好吧,我稍后会查看并编辑这个答案。但是现在,如果你有一个不超过,我不知道,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)

请备份您的实际文件之前运行这个,因为它可能会把整个事情搞砸。(未经测试)

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')

maskdf['ID']分组,如果原始mask中的任何值为真,则将True分配给该组的所有行,否则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为真的行:

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

相关问题 更多 >