2015-07-01 4 views
0

у меня есть 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 является осокой или Carcra Я хочу изменить 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 
+0

Я упрощая CSV здесь, все, что нужно изменить, потому что я собираюсь быть суммированием на основе 'ID' в конце концов, и если только значение 'D' изменяет значение из' C', будет оставлено в старом классе. Надеюсь, что это имеет смысл. –

+0

Пожалуйста, сделайте желаемый результат согласованным с критериями, как вы заявили об этом в вопросе. – unutbu

+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 всех строк этой группы, если любого значения в исходном 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 верно:

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 
+0

Это возвратило 1 столбец 'FALSE' –

+0

. Вышеприведенный код должен работать на данные, которые вы опубликовали, и соответствует вашему описанию критериев, если не желаемый результат. Поскольку мы ничего не знаем о вашем реальном CSV, все, что мы можем попытаться сделать, - это решить проблему, поскольку она ставится в вопросе. Я понятия не имею, почему приведенный выше код должен привести к столбцу значений FALSE. – unutbu

+0

Я создал DataFrame, идентичный тому, который был отправлен, и он возвращает: True, False, False, True, False, False, False, False, False –

0

Вы отметили pandas, так что я предполагаю, что вы можете импортировать это в виде данных.

Если да, то я думаю, что вы ищете что-то вроде этого:

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

Это вернуло 'TypeError: не может сравнить массив dtyped [object] со скаляром типа [bool] ' –

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) 

Пожалуйста, пожалуйста, пожалуйста, создайте резервную копию своего фактического файла перед запуском этого, потому что это может испортить всю вещь. (Непроверенная)

Смежные вопросы