Условное удаление элементов из значений, разделенных запятыми, в столбцах фрейма данных - PullRequest
0 голосов
/ 23 сентября 2019

Скажем, у меня есть фрейм данных с 4 столбцами, где два столбца - это значения элементов, разделенные запятыми, а два других столбца - просто значение.

    df.head()
    col1 col2 col3  col4     col5
    a.    34  67 34,44,55  41,54,67
    b.    75   105  75,90   85 105

И мне нужно удалить первый элемент из col4, если он равен значению в col2.И так, я хочу удалить последний элемент в col5, если он равен col3.

В конце фрейм данных должен выглядеть следующим образом:

 df2.head()

    col1 col2 col3  col4     col5
    a.    34   67   44,55  41,54
    b.    75   105   90   85

Я пытался использовать:

df.col4.map(lambda x: x.pop(0))
AttributeError: 'str' object has no attribute 'pop'

Любые предложения или помощь приветствуется.

Ответы [ 4 ]

1 голос
/ 23 сентября 2019

split col4 и col5 на серию списков s4, s5.Затем используйте np.where, чтобы сравнить col2 с s4 и col3 с s5 и join списком, чтобы выстроить строку как нужно

s4 = df.col4.str.split(',\s*|\s+')
s5 = df.col5.str.split(',\s*|\s+') 
df['new_col4'] = np.where(df.col2.eq(s4.str[0].astype(int)), s4.str[1:].str.join(','), df.col2)
df['new_col5'] = np.where(df.col3.eq(s5.str[-1].astype(int)), s5.str[:-1].str.join(','), df.col3)

Out[358]:
  col1  col2  col3      col4      col5 new_col4 new_col5
0   a.    34    67  34,44,55  41,54,67    44,55    41,54
1   b.    75   105    75,90     85 105       90       85
1 голос
/ 23 сентября 2019

Допустим, ваш фрейм данных определен как:

df = pd.DataFrame(data=[[34, 67, "34,44,55", "41,54,67"], [75, 105, "75,90", "85,105"]], columns=["col2","col3","col4","col5"])

Вы получаете следующий фрейм данных:

   col2 col3  col4      col5
0   34  67    34,44,55  41,54,67
1   75  105   75,90     85,105

Вы можете использовать .apply() с axis=1 применить функцию к каждой строке данных.

В этой функции вы сначала конвертируете свою строку в col4 (or col5) в список, разбив на ,.Затем в col2 (or col3).

df["col4"] = df.apply(lambda row: ",".join([item for item in row["col4"].split(",") if int(item) != row["col2"]]), axis=1)
df["col5"] = df.apply(lambda row: ",".join([item for item in row["col5"].split(",") if int(item) != row["col3"]]), axis=1)

вы можете перебирать элементы в списке и сохранять только те, которые не равны целому числу. Вот результат, который вы получите:

    col2    col3    col4    col5
0   34      67      44,55   41,54
1   75      105     90      85
1 голос
/ 23 сентября 2019

Видимо, у вас есть нерешенная проблема с пробелами, вы можете решить ее.Но это учитывает ваши потребности:

df['col4'] = df.apply(lambda row: row['col4'] if row['col4'].split(',')[0].strip() != str(row['col2']) else ','.join(row['col4'].split(',')[1:]), axis=1)
df['col5'] = df.apply(lambda row: row['col5'] if row['col5'].split(',')[-1].strip() != str(row['col3']) else ','.join(row['col5'].split(',')[:-1]), axis=1)
1 голос
/ 23 сентября 2019

кажется, что значения col4 на самом деле являются строками, а не списками - вы должны использовать split(',') в них (и, возможно, приведите их обратно к str после редактирования, зависит от того, что вы планируете делать позже).Также pop() вернет элемент, так что, возможно, срез будет лучше: lambda x: x.split(',')[1:]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...