==
сравнивает ссылки на объекты в Java и не является исключением для объектов String
.
Для сравнения фактического содержимого объектов (в том числе String
) необходимо использовать equals
.
Если сравнение двух объектов String
с использованием ==
оказывается true
, это связано с тем, что объекты String
были интернированы, а виртуальная машина Java имеет несколько ссылки указывают на тот же экземпляр String
. Не следует ожидать сравнения одного объекта String
, содержащего то же содержимое, что и другой объект String
, используя ==
для оценки как true
.
еще один способ сделать это:
df['period'] = df['Year'].astype(str) + df['quarter']
или бит медленнее:
df['period'] = df[['Year','quarter']].astype(str).sum(axis=1)
Давайте проверим его на 200K строках DF:
In [250]: df
Out[250]:
Year quarter
0 2014 q1
1 2015 q2
In [251]: df = pd.concat([df] * 10**5)
In [252]: df.shape
Out[252]: (200000, 2)
UPDATE: график времени Pandas 0.23.0
UPDATE: новые тайминги с использованием Pandas 0.19.0
Сроки без CPU / GPU (отсортировано от самого быстрого до самого медленного):
In [107]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 131 ms per loop
In [106]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 161 ms per loop
In [108]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 189 ms per loop
In [109]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 567 ms per loop
In [110]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 584 ms per loop
In [111]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 24.7 s per loop
Сроки с использованием оптимизации CPU / GPU:
In [113]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 53.3 ms per loop
In [114]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 65.5 ms per loop
In [115]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 79.9 ms per loop
In [116]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [117]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [118]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 9.38 s per loop
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['period'] = df[['Year', 'quarter']].apply(lambda x: ''.join(x), axis=1)
Устанавливает этот фрейм данных
Year quarter period
0 2014 q1 2014q1
1 2015 q2 2015q2
Этот метод обобщает на произвольное количество столбцов строки, заменив df[['Year', 'quarter']]
на любой фрагмент столбца вашего фрейма данных, например. df.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
.
Вы можете проверить дополнительную информацию о методе apply () здесь
lambda x: ''.join(x)
ничего не делает; это похоже на lambda x: sum(x)
, а не только на sum
.
– DSM
1 February 2017 в 22:07
''.join
, т. Е .: df['period'] = df[['Year', 'quarter']].apply(''.join, axis=1)
.
– Max Ghenis
10 October 2017 в 05:30
join
принимает только экземпляры str
в итерабельном. Используйте map
, чтобы преобразовать их все в str
, а затем используйте join
.
– John Strood
27 March 2018 в 12:51
Метод cat()
аксессуара .str
отлично работает для этого:
>>> import pandas as pd
>>> df = pd.DataFrame([["2014", "q1"],
... ["2015", "q3"]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 q1
1 2015 q3
>>> df['Period'] = df.Year.str.cat(df.Quarter)
>>> print(df)
Year Quarter Period
0 2014 q1 2014q1
1 2015 q3 2015q3
cat()
даже позволяет вам добавить разделитель, поэтому для Например, предположим, что у вас есть только целые числа в течение года и периода, вы можете сделать это:
>>> import pandas as pd
>>> df = pd.DataFrame([[2014, 1],
... [2015, 3]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 1
1 2015 3
>>> df['Period'] = df.Year.astype(str).str.cat(df.Quarter.astype(str), sep='q')
>>> print(df)
Year Quarter Period
0 2014 1 2014q1
1 2015 3 2015q3
Объединение нескольких столбцов - это просто передача списка серий или данных, содержащих все, кроме первого столбца как параметр str.cat()
, вызываемый в первом столбце (серии):
>>> df = pd.DataFrame(
... [['USA', 'Nevada', 'Las Vegas'],
... ['Brazil', 'Pernambuco', 'Recife']],
... columns=['Country', 'State', 'City'],
... )
>>> df['AllTogether'] = df['Country'].str.cat(df[['State', 'City']], sep=' - ')
>>> print(df)
Country State City AllTogether
0 USA Nevada Las Vegas USA - Nevada - Las Vegas
1 Brazil Pernambuco Recife Brazil - Pernambuco - Recife
lambda
или map
; также он просто читает самое чистое.
– dwanderson
22 May 2016 в 20:31
str.cat()
. Я исправлю ответ
– LeoRochael
23 July 2018 в 21:42
dataframe["period"] = dataframe["Year"].map(str) + dataframe["quarter"]
add(dataframe.iloc[:, 0:10])
?
– Heisenberg
9 May 2015 в 19:15
dataframe["period"] = dataframe["Year"].map(str) + dataframe["quarter"].map(str)
, карта просто применяет преобразование строк ко всем записям.
– Ozgur Ozturk
1 February 2017 в 22:17
Хотя ответ @silvado хорош, если вы меняете df.map(str)
на df.astype(str)
, это будет быстрее:
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
In [131]: %timeit df["Year"].map(str)
10000 loops, best of 3: 132 us per loop
In [132]: %timeit df["Year"].astype(str)
10000 loops, best of 3: 82.2 us per loop
Использование zip
может быть еще более быстрым:
dataframe["period"] = ([''.join(i) for i in
zip(dataframe["Year"].map(str),dataframe["quarter"])])
В наборе данных ниже zip()
был наиболее удачным из всех: https://stackoverflow.com/a/50316945/ 7386332
import pandas as pd
data = '''\
ID,Host,Protocol,Port
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,445
1,10.0.0.10,tcp,49707
1,10.0.0.10,tcp,49672
1,10.0.0.10,tcp,49670'''
df = pd.read_csv(pd.compat.StringIO(data)) # Recreates a sample dataframe
df = pd.concat([df]*10000)
%timeit df['Host'] + "/" + df['Protocol'] + "/" + df['Port'].map(str)
%timeit ['/'.join(i) for i in zip(df['Host'],df['Protocol'],df['Port'].map(str))]
%timeit ['/'.join(i) for i in df[['Host','Protocol','Port']].astype(str).values]
10 loops, best of 3: 39.7 ms per loop
10 loops, best of 3: 35.9 ms per loop
10 loops, best of 3: 162 ms per loop
Использование лямбда-функции на этот раз с помощью string.format ().
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': ['q1', 'q2']})
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
print df
Quarter Year
0 q1 2014
1 q2 2015
Quarter Year YearQuarter
0 q1 2014 2014q1
1 q2 2015 2015q2
Это позволяет вам работать с ненулевыми и переформатировать значения по мере необходимости.
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': [1, 2]})
print df.dtypes
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}q{}'.format(x[0],x[1]), axis=1)
print df
Quarter int64
Year object
dtype: object
Quarter Year
0 1 2014
1 2 2015
Quarter Year YearQuarter
0 1 2014 2014q1
1 2 2015 2015q2
def madd(x):
"""Performs element-wise string concatenation with multiple input arrays.
Args:
x: iterable of np.array.
Returns: np.array.
"""
for i, arr in enumerate(x):
if type(arr.item(0)) is not str:
x[i] = x[i].astype(str)
return reduce(np.core.defchararray.add, x)
Например:
data = list(zip([2000]*4, ['q1', 'q2', 'q3', 'q4']))
df = pd.DataFrame(data=data, columns=['Year', 'quarter'])
df['period'] = madd([df[col].values for col in ['Year', 'quarter']])
df
Year quarter period
0 2000 q1 2000q1
1 2000 q2 2000q2
2 2000 q3 2000q3
3 2000 q4 2000q4
более эффективен
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
, и вот время:
import numpy as np
import pandas as pd
from time import time
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
def concat_df_str2(df):
""" run time: 5.2758s """
return df.astype(str).sum(axis=1)
def concat_df_str3(df):
""" run time: 5.0076s """
df = df.astype(str)
return df[0] + df[1] + df[2] + df[3] + df[4] + \
df[5] + df[6] + df[7] + df[8] + df[9]
def concat_df_str4(df):
""" run time: 7.8624s """
return df.astype(str).apply(lambda x: ''.join(x), axis=1)
def main():
df = pd.DataFrame(np.zeros(1000000).reshape(100000, 10))
df = df.astype(int)
time1 = time()
df_en = concat_df_str4(df)
print('run time: %.4fs' % (time() - time1))
print(df_en.head(10))
if __name__ == '__main__':
main()
final, когда используется sum
(concat_df_str2), результат не просто concat, он преобразуется в целое число.
df.values[:, 0:3]
или df.values[:, [0,2]]
.
– Snow bunting
9 February 2018 в 10:51
Используйте .combine_first
.
df['Period'] = df['Year'].combine_first(df['Quarter'])
мой ответ немного запоздал, но я думаю, что позже лучше, чем никогда. Предположим, что ваш dataframe
- df
со столбцами Year
и Quarter
.
import pandas as pd
df = pd.DataFrame({'Quarter':'q1 q2 q3 q4'.split(), 'Year':'2000'})
Предположим, что мы хотим видеть фрейм данных;
df
>>> Quarter Year
0 q1 2000
1 q2 2000
2 q3 2000
3 q4 2000
Наконец , соедините Year
и Quarter
следующим образом.
df['Period'] = df['Year'] + ' ' + df['Quarter']
Теперь вы можете print
df
видеть результирующий фрейм.
df
>>> Quarter Year Period
0 q1 2000 2000 q1
1 q2 2000 2000 q2
2 q3 2000 2000 q3
3 q4 2000 2000 q4
Если вам не нужно пространство между годом и кварталом, просто удалите его, выполнив:
df['Period'] = df['Year'] + df['Quarter']
Надеюсь, это вам поможет.
df['Period'] = df['Year'].map(str) + df['Quarter'].map(str)
– Stuber
7 August 2018 в 18:58
Вот реализация, которую я нахожу очень универсальной:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame([[0, 'the', 'quick', 'brown'],
...: [1, 'fox', 'jumps', 'over'],
...: [2, 'the', 'lazy', 'dog']],
...: columns=['c0', 'c1', 'c2', 'c3'])
In [3]: def str_join(df, sep, *cols):
...: from functools import reduce
...: return reduce(lambda x, y: x.astype(str).str.cat(y.astype(str), sep=sep),
...: [df[col] for col in cols])
...:
In [4]: df['cat'] = str_join(df, '-', 'c0', 'c1', 'c2', 'c3')
In [5]: df
Out[5]:
c0 c1 c2 c3 cat
0 0 the quick brown 0-the-quick-brown
1 1 fox jumps over 1-fox-jumps-over
2 2 the lazy dog 2-the-lazy-dog
Как уже упоминалось ранее, вы должны преобразовать каждый столбец в строку и затем использовать оператор плюс для объединения двух столбцов строки. Вы можете получить большое улучшение производительности, используя NumPy.
%timeit df['Year'].values.astype(str) + df.quarter
71.1 ms ± 3.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df['Year'].astype(str) + df['quarter']
565 ms ± 22.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Когда ваши данные вставлены в кадр данных, эта команда должна решить вашу проблему:
df['period'] = df[['Year', 'quarter']].apply(lambda x: ' '.join(x.astype(str)), axis=1)