Вот функция , которую я написал для этой общей задачи. Это более эффективно, чем методы Series
/ stack
. Колонка и имена сохраняются.
def tidy_split(df, column, sep='|', keep=False):
"""
Split the values of a column and expand so the new DataFrame has one split
value per row. Filters rows where the column is missing.
Params
------
df : pandas.DataFrame
dataframe with the column to split and expand
column : str
the column to split and expand
sep : str
the string used to split the column's values
keep : bool
whether to retain the presplit value as it's own row
Returns
-------
pandas.DataFrame
Returns a dataframe with the same columns as `df`.
"""
indexes = list()
new_values = list()
df = df.dropna(subset=[column])
for i, presplit in enumerate(df[column].astype(str)):
values = presplit.split(sep)
if keep and len(values) > 1:
indexes.append(i)
new_values.append(presplit)
for value in values:
indexes.append(i)
new_values.append(value)
new_df = df.iloc[indexes, :].copy()
new_df[column] = new_values
return new_df
С помощью этой функции исходный вопрос прост как:
tidy_split(a, 'var1', sep=',')
К сожалению, эта сокращенная нотация (которая вызывает «Символ # to_proc») не имеет способа передать аргументы вызываемому методу или блоку, поэтому вы даже не можете сделать следующее:
array_of_strings.map(&:include, 'l') #=> this would fail
НО, вам повезло, потому что вам действительно не нужен этот ярлык , чтобы делать то, что вы пытаетесь сделать. Амперсанд может преобразовать Proc или Lambda в блок, и наоборот:
my_routine = Proc.new { |str| str.upcase }
%w{ one two three }.map &my_routine #=> ['ONE', 'TWO', 'THREE']
Обратите внимание на отсутствие двоеточия до my_routine
. Это связано с тем, что мы не хотим преобразовать символ :my_routine
в proc, найдя метод и вызывая .method
на нем, вместо этого мы хотим преобразовать my_routine
Proc в блок и передать его в map
.
Зная это, вы даже можете сопоставить собственный метод Ruby:
%w{ one two three }.map &method(:p)
Метод method
будет принимать метод p
и преобразовывать его в Proc, и &
преобразует его в блок, который передается в map
. В результате каждый элемент печатается. Это эквивалентно этому:
%w{ one two three }.map { |s| p s }